SitePoint Sponsor

User Tag List

Page 1 of 2 12 LastLast
Results 1 to 25 of 42
  1. #1
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    Anybody wanna walk through a TDD session with me?

    I've been playing around with Unit Testing for past couple of weeks now. Every bit of code I've written has been tested with SimpleTest since I started. However, I want to try to get my head around using Unit Testing for TDD. I could self-teach myself it; and I will do but it would be useful to me (and probably others) if I could chronicle a basic session here.

    Anybody wanna help me along with it? Or maybe you're just learning TDD yourself and wanna join in.

    I've nearly finished my first basic TDD session on another forum where we built a (basic) HTTP request class but I have a feeling I may get some more adavice from more seasoned XP'ers on this forum.

    I only want to walk through the design of something basic, but preferrably something which requires me to make use of Mocks/Partial Mocks.

    The idea I had was a web page caching system. For example, you have a web page which displays dynamic data from a database. In reality, the data in the DB only changes every 60 mins though and the computations you make on it may be complex/resource hogging so this class would cache the page for 1 hour and every subsequent request simply receives the cached version.

    Does this sound like a basic enough example to walk through?

  2. #2
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Why has this been moved from PHP Application Design into PHP Code? There was another walkthrough done in there in the past with McGruff and Jason Sweat so why is mine any different?

    Nobody discusses TDD in this board. Never mind, doesn't matter.

  3. #3
    SitePoint Addict GeertDD's Avatar
    Join Date
    Feb 2005
    Location
    Belgium
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Before I read this topic, I had never even heard of TDD. Had to google for it. Then I read through the HTTP request class topic. I do get the concept now. Interesting way of coding. A hard part for me seems to be with what test to come up next asking the questions. But once you have those, coding the answers gets a whole lot more goal-orientated.

    Since I've been looking for a simple caching system as well lately, I'll surely follow this topic closely. Obviously, I'm not the seasoned coder you'll learn a lot from, but I've been thinking about the first test: setting the cache directory for example?

  4. #4
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by GeertDD
    Before I read this topic, I had never even heard of TDD. Had to google for it. Then I read through the HTTP request class topic. I do get the concept now. Interesting way of coding. A hard part for me seems to be with what test to come up next asking the questions. But once you have those, coding the answers gets a whole lot more goal-orientated.

    Since I've been looking for a simple caching system as well lately, I'll surely follow this topic closely. Obviously, I'm not the seasoned coder you'll learn a lot from, but I've been thinking about the first test: setting the cache directory for example?
    My thoughts... testing that the directory is set may be a little superfluous. I'm inclined to think that testing setters is a little pointless. Any issues with setters (typos or such) would appear in more in-depth tests anyway. So I'd be thinking of something like this:

    PHP Code:
    class TestOfPageCache extends UnitTestCase
    {
        public function 
    testCacheIsWritable()
        {
            
    $cache = new PageCache('mypage');
            
    $cache->setCacheDirectory('./cache');
            
    $this->assertTrue($cache->isWritable());
        }

    Which has just resulted in me writing this:

    PHP Code:
    class PageCache
    {
        protected 
    $cacheDirectory '/tmp';
        
        public function 
    __construct($pagename)
        {
            
    //
        
    }
        
        public function 
    setCacheDirectory($path)
        {
            
    $this->cacheDirectory $path;
        }
        
        public function 
    isWritable()
        {
            return 
    is_writable($this->cacheDirectory);
        }


  5. #5
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So then, we want to be able to cache unique entries right? Or at least user-defined ones.

    The test:
    PHP Code:
    class TestOfPageCache extends UnitTestCase
    {
        public function 
    testCacheIsWritable()
        {
            
    $cache = new PageCache('mypage');
            
    $cache->setCacheDirectory('./cache');
            
    $this->assertTrue($cache->isWritable());
            @
    fopen('./cache/test.txt''w+');
            
    $this->assertTrue(file_exists('./cache/test.txt'));
            @
    unlink('./cache/test.txt');
            
    $this->assertFalse(file_exists('./cache/test.txt'));
        }
        
        public function 
    testPageCacheFileIsCreated()
        {
            
    $cache = new PageCache('mypage');
            
    $cache->setCacheDirectory('./cache');
            
    $this->assertTrue($cache->isWritable());
            
    $cache->updatePage();
            
    $this->assertTrue(file_exists('./cache/mypage'));
            @
    unlink('./cache/mypage');
            
    $this->assertFalse(file_exists('./cache/mypage'));
        }

    The Code:
    PHP Code:
    class PageCache
    {
        protected 
    $cacheDirectory '/tmp';
        protected 
    $page;
        
        public function 
    __construct($pagename)
        {
            
    $this->page $pagename;
        }
        
        public function 
    setCacheDirectory($path)
        {
            
    $this->cacheDirectory $path;
        }
        
        public function 
    isWritable()
        {
            return 
    is_writable($this->cacheDirectory);
        }
        
        public function 
    updatePage()
        {
            if (
    $this->isWritable())
            {
                
    $handle fopen($this->cacheDirectory.'/'.$this->page'w+');
                
    fclose($handle);
            }
        }


  6. #6
    SitePoint Addict GeertDD's Avatar
    Join Date
    Feb 2005
    Location
    Belgium
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay. I tried something. Just gave it a shot. Keep in mind this is the first time ever I coded this way. Was happy already that I was able to set up a Simple Test environment.

    Enough excuses. I modified testPageCacheFileIsCreated() in order to check whether we could really write some text to it. Not sure whether that is the next logical step?
    PHP Code:
    class TestOfPageCache extends UnitTestCase
    {
        function 
    testCacheIsWritable()
        {
            
    $cache = new PageCache('mypage');
            
    $cache->setCacheDirectory('./cache');
            
    $this->assertTrue($cache->isWritable());
            @
    fopen('./cache/test.txt''w+');
            
    $this->assertTrue(file_exists('./cache/test.txt'));
            @
    unlink('./cache/test.txt');
            
    $this->assertFalse(file_exists('./cache/test.txt')); 
        }
        
        function 
    testPageCacheFileIsCreated()
        {
            
    $cache = new PageCache('mypage');
            
    $cache->setCacheDirectory('./cache');
            
    $this->assertTrue($cache->isWritable());
            
    $cache->updatePage('Dummy'); // added $data parameter
            
    $this->assertTrue(file_exists('./cache/mypage'));
            
    // added the test below:
            
    $this->assertIdentical($cache->loadPage(), 'Dummy');
            @
    unlink('./cache/mypage');
            
    $this->assertFalse(file_exists('./cache/mypage'));
        }

    Uh-oh, and here comes my updated PageCache class. (I'm really sorry about the php4 code. )
    PHP Code:
    class PageCache
    {
        var 
    $cacheDirectory '/tmp';
        var 
    $page;
        
        function 
    PageCache($pagename)
        {
           
    $this->page $pagename;
        }
        
        function 
    setCacheDirectory($path)
        {
            
    $this->cacheDirectory $path;
        }
        
        function 
    isWritable()
        {
            return 
    is_writable($this->cacheDirectory);
        }
        
        function 
    updatePage($data)
        {
            if (
    $this->isWritable())
            {
                
    $handle fopen($this->cacheDirectory.'/'.$this->page'w+');
                
    fwrite($handle$data);
                
    fclose($handle);
            } 
        }
        
        function 
    loadPage()
        {
            
    $filename $this->cacheDirectory'/' .$this->page;
            
            
    // check cacheDirectory
            
    if (!$this->isWritable()) // An isReadable method would be superfluous, I guess?
                
    return FALSE;
                
            
    // check cacheFile, or is this redundant?
            
    if (!file_exists($filename))
                return 
    FALSE;
                
            
    // read and return content
            
    $handle fopen($filename'r');
            
    $content fread($handlefilesize($filename));
            
    fclose($handle);
            
            return 
    $content;
        }


  7. #7
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hehe... This is interesting. I actually finished this yesterday and already went down a different route so I'm gonna continue down your route in this thread and see what happens I won't show you my code since it might (probably will) jade the concept.

  8. #8
    is_empty(2); foofoonet's Avatar
    Join Date
    Mar 2006
    Posts
    1,000
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    never mind

    Last edited by foofoonet; Aug 25, 2006 at 04:00. Reason: incorrect information
    Upgrading to Mysql 5? Auto-increment fields now strict
    use NULL
    Or zero or leave the field name out completely.

  9. #9
    Mlle. Ledoyen silver trophy seanf's Avatar
    Join Date
    Jan 2001
    Location
    UK
    Posts
    7,168
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by d11wtq
    Why has this been moved from PHP Application Design into PHP Code?
    I'm not sure why a moderator decided to move this, but I have moved it back to PHP Application Design

    Sean
    Harry Potter

    -- You lived inside my world so softly
    -- Protected only by the kindness of your nature

  10. #10
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by seanf
    I'm not sure why a moderator decided to move this, but I have moved it back to PHP Application Design

    Sean
    Thank you

  11. #11
    SitePoint Addict GeertDD's Avatar
    Join Date
    Feb 2005
    Location
    Belgium
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Pfew, this isn't as easy as it seems to me. At least I'm learning tons of new stuff here.

    There has been a lack of updates from my side because I bought a new iMac just yesterday (amazing machine). Today I installed a local Apache webserver on my Mac, with php5!

    Think I'm just going to start over and hope to come up with something tomorrow. I've been doodling already a bit on paper. Below are the tests I vaguely have in mind. We'll see how this works out.

    - cacheIsWritable
    - cacheIsWrittenTo
    - cacheIsReadFrom
    - cacheIsExpired
    - cacheIsCleared

  12. #12
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    You seem to have jumped right into a decision that your cache should be file based (setCacheDir and such). Wouldn't it be better to decide how your client code wants to interact with the cache and design the API from there? What if you later want to have caching mechanisms which are not file based (memcache?)?

    A couple of years ago I wrote (and tested) a data cache project for a presentation. The project lives on sourceforge

    It was different from what I believe you are trying to achieve in that my data cache was trying to store variables, whereas you are aiming at the text of the entire page.

    an example of my file based cached test was: http://phpdatacache.cvs.sourceforge.....1&view=markup

    Here was the abstract base class for my cache objects:
    http://phpdatacache.sourceforge.net/...aCacheDAO.html

    boiled down to three methods:

    isCached($key)
    setCache($key,$value)
    getCache($key)
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  13. #13
    SitePoint Addict GeertDD's Avatar
    Join Date
    Feb 2005
    Location
    Belgium
    Posts
    334
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, I tried to simplify my class a bit, but I still end up with quite a lot more methods than three.

    Concerning the data vs entire page caching, actually I'm not specifically aiming at one of them. The class should be able to handle both, I guess. Anyway, in the first place this is an exercise for me: first time coding php5, first time really using file functions, first time applying TDD, first time coding in camelBagStyle (lol).

    Here's what I ended up with for now. It won't be perfect, may not even get near to it, but hey, the best way to learn is from your own mistakes. I'd love some more advice, thanks.

    PHP Code:
    class TestCacheEngine extends UnitTestCase {

        function 
    testCacheIsWritable() {
            
            
    $cache = new CacheEngine('myCache');
            
    $cache->setCacheDir('./cache');
            
    $this->assertTrue($cache->cacheIsWritable());
        }
        
        function 
    testCacheIsUpdated() {
        
            
    $cache = new CacheEngine('myCache');
            
    $cache->setCacheDir('./cache');
            
    $cache->writeToCache('dummy cache text');
            
    $this->assertTrue(file_exists('./cache/myCache'));
            
    $this->assertIdentical($cache->readFromCache(), 'dummy cache text');
        }
        
        function 
    testCacheIsExpired() {
        
            
    $cache = new CacheEngine('myCache');
            
    $cache->setCacheDir('./cache');
            
    $cache->writeToCache('dummy cache text');
            
    $cache->setCacheLifetime(1);
            
    $this->assertFalse($cache->cacheIsExpired());
            
    sleep(1);
            
    $this->assertTrue($cache->cacheIsExpired());
        }
        
        function 
    testCacheIsDeleted() {
        
            
    $cache = new CacheEngine('myCache');
            
    $cache->setCacheDir('./cache');
            
    $cache->writeToCache('dummy cache text');
            
    $this->assertTrue(file_exists('./cache/myCache'));
            
    $cache->deleteFromCache();
            
    $this->assertFalse(file_exists('./cache/myCache'));
        }

    PHP Code:
    class CacheEngine {

        public 
    $cacheDir;
        public 
    $cacheFile;
        public 
    $cacheLifetime;

        public function 
    __construct($id) {
        
            
    $this->cacheFile $id;
        }
        
        public function 
    setCacheDir($dir) {
        
            
    $this->cacheDir $dir;
        }
        
        public function 
    cacheIsWritable() {
        
            return 
    is_writable($this->cacheDir);
        }
        
        public function 
    writeToCache($data) {
        
            
    $handle fopen($this->cacheDir .'/'$this->cacheFile'w+');
            
    fwrite($handle$data);
            
    fclose($handle);
        }
        
        public function 
    readFromCache() {
        
            
    $handle fopen($this->cacheDir .'/'$this->cacheFile'r');
            
    $contents fread($handlefilesize($this->cacheDir .'/'$this->cacheFile));
            
    fclose($handle);
            
            return 
    $contents;
        }
        
        public function 
    setCacheLifetime($seconds) {
        
            
    $this->cacheLifetime $seconds;
        }
        
        public function 
    cacheIsExpired() {
        
            
    $deadline time() - $this->cacheLifetime;
            
    $cacheTime filemtime($this->cacheDir .'/'$this->cacheFile);
            return (
    $cacheTime $deadline) ? FALSE TRUE;
        }
        
        public function 
    deleteFromCache() {
        
            
    unlink($this->cacheDir .'/'$this->cacheFile);
        }


  14. #14
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Jason is right... can we pass it some abstract caching mechanism and forget about fgets and all that stuff in the main class, providing only methods such as:

    startCaching()
    commit()
    clean()
    get()
    hasExpired()

    EDIT | I can already see a need for ob_ in this.... bad thing?

  15. #15
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I though about how I wanted to use the code:

    PHP Code:
    $cache = new ThisCacheThing;
    if (
    $cache->valid('thispage')) {
      echo 
    $cache->getCache('thispage');
    } else {
      
    $page expensive_page_generation();
      
    $cache->set('thispage',$page);
      echo 
    $page;

    Harry pointed out the "cache" portions of the method names were redundant with the variable name, so doing it now I would probably change the three methods to:

    valid($key);
    set($key,$value);
    get($key);

    settle on some simple methods for your API, then start with some simple tests, perhaps:

    function testUnsetCacheKeyIsInvalid()

    and so on.

    Later, when your basic mechanism is working, add in some facier requirements like clearing, cache expiration, etc.

    So, what does a day in the life of your cache object look like in real use?
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  16. #16
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    OK, so going back to scratch here. I'm assuming the best thing do would be to make an asbtract class to do the actual reading and writing stuff (so that it can be swapped for other storage media), and have the stuff to actually manage the page contents and display the data etc in the main class.

    So the obvious place to start is by testing the interface of the abstract class. Nothing tiresome just backs like Jason already just mentioned. From there we can mock the abstract class to use as a helper in testing our main class. I think we're safe to assume that if the abstract class was tested to behave as expected there's not even a real need to really save a file or whatever, the mock can just pretend like we did.

    Here's a little test to make a start on the abstract class... it seems so completely pointless of a test But I've seen other people start tests by doing obvious things like just forcing a TRUE value to make a true assertion pass the test. I guess as you progress, you need to keep that test passing but with other conditions surrounding it.

    PHP Code:
    class TestOfCacheMechanism extends UnitTestCase
    {
        public function 
    testExistingFileIsValid()
        {
            
    Mock::GeneratePartial('FileCache''PartialFileCache', array('exists'));
            
    $fileCache = new PartialFileCache($this);
            
    $fileCache->setReturnValue('exists'true);
            
    $this->assertTrue($fileCache->isValid('anything'));
        }

    Code
    PHP Code:
    abstract class CacheMechanism
    {
        public function 
    isValid($key);
    }

    class 
    FileCache extends CacheMechanism
    {
        public function 
    isValid($key)
        {
            return 
    $this->exists($key);
        }

        public function 
    exists($key) {}


  17. #17
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So you might test:
    PHP Code:
    class TestFileCache extends UnitTestCase {
      function 
    testUnsetKeyIsValidReturnsFalse() {
        
    $cache = new FileCache;
        
    $this->assertFalse($cache->isValid('some key'));
      }

    And with what you are describing so far perhaps:
    PHP Code:
    interface Cache {
      function 
    isValid($key);
    }
    class 
    FileCache implements Cache {
      function 
    isValid($key) {
      }

    Passes from the get go (with an empty isValid method). Now we would want to be able to set the cache, and validate the isValid() function returns true after setting:

    PHP Code:
    class TestFileCache extends UnitTestCase {
      function 
    testUnsetKeyIsValidReturnsFalse() {...}
      function 
    testIsValidTrueAfterSet() {
        
    $cache = new FileCache;
        
    $this->assertFalse($cache->isValid('some key'));
        
    $this->assertTrue($cache->set('some key''some data'));
        
    $this->assertTrue($cache->isValid('some key'));
      } 

    So what would happen next?
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  18. #18
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Well we could use a container in the class to store keys => data but that seems a bit intensive for a file storage system, nor is it persistent. We want cahced data to be available to any client, upon any number of requests providing it was set previously. Before I write the code... do I *need* to create a file, or can I mock this behaviour? I wasn't sure how you'd mock it really.

  19. #19
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmmm... wait. I think I've lost focus of the objective here. We're not testing that a file storage caching mechanism works... we're just testing interface, so on that note (no longer called FileCache... just DummyCache :P)

    PHP Code:
    interface Cache
    {
        public function 
    set($key$value);
        public function 
    isValid($key);
    }

    class 
    DummyCache implements Cache
    {
        protected 
    $keys = array();
        
        public function 
    set($key$value)
        {
            
    $this->keys[$key] = $value;
        }

        public function 
    isValid($key)
        {
            return isset(
    $this->keys[$key]);
        }

    EDIT | Forgot to include the test

    PHP Code:
    class TestCache extends UnitTestCase
    {
        function 
    testUnsetKeyIsValidReturnsFalse()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->get('something'));
        }

        function 
    testIsValidTrueAfterSet()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->isValid('something'));
            
    $this->assertTrue($cache->set('something''some data'));
            
    $this->assertTrue($cache->isValid('something'));
        }

    Last edited by Chris Corbyn; Aug 26, 2006 at 11:34.

  20. #20
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    So, I guess we need to add the get() method.

    PHP Code:
    class TestCache extends UnitTestCase
    {
        public function 
    testUnsetKeyIsValidReturnsFalse()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->get('something'));
        }

        public function 
    testIsValidTrueAfterSet()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->isValid('something'));
            
    $this->assertTrue($cache->set('something''some data'));
            
    $this->assertTrue($cache->isValid('something'));
        }

        public function 
    testGettingUnsetKeyReturnsFalse()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->get('something'));
        }
        
        public function 
    testGettingSetKeyContainsExactData()
        {
            
    $cache = new Cache;
            
    $this->assertFalse($cache->get('something'));
            
    $cache->set('something''some data');
            
    $this->assertIdentical('some data'$cache->get('something'));
        }

    Code...
    PHP Code:
     interface Cache
    {
        public function 
    set($key$value);
        public function 
    get($key);
        public function 
    isValid($key);
    }

    class 
    DummyCache implements Cache
    {
        protected 
    $keys = array();
        
        public function 
    set($key$value)
        {
            
    $this->keys[$key] = $value;
        }
        
        public function 
    get($key)
        {
            if (
    $this->isValid($key))
            {
                return 
    $this->keys[$key];
            }
            else return 
    false;
        }

        public function 
    isValid($key)
        {
            return isset(
    $this->keys[$key]);
        }


  21. #21
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Ok, what behavior should be next? Your cache object is supposed to be used between requests to cache the data, right? Well, it is hard to simulate that in a single test, but effectivly what you are talking about at that point is that any instance of the cache you create will return the same data for the same key. This effectively makes the cache exhibit the MonoState pattern.

    How can you test this? Perhaps...

    PHP Code:
    class TestCache extends UnitTestCase
    {
      
    //....
      
    function testCacheIsAMonoStateObject() {
        
    $cache = new FileCache;
        
    $value rand(0,100);
        
    $cache->set('key',$value);
        
    $this->assertEqual($value,$cache->get('key'));

        
    $cache2 = new FileCache;
        
    $this->assertEqual($value,$cache2->get('key'));
      }

    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  22. #22
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hmm... that's not what I was thinking of testing next (I was thinking of testing the method which checks it's age since we need a timeout but we can't get the ade from the main class since we have this level of abstraction and checking age may vary depeding upon the mechanism... as will clearing the cache... christ... wtf is the main class object actually going to do )

    To pass your test it's either got to be a singleton (nasty), apply a setting to a gloabl (more simulated), or a static (samne sort of thing).

    I'm gonna go with a static variable for the sake of the tests. It doesn't quite fell right but creating a file seems a bit too much like we're testing a specific implementation of the cache rather than just the concept of it.

    PHP Code:
    class DummyCache implements Cache
    {
        protected static 
    $keys = array();
        
        public function 
    set($key$value)
        {
            
    self::$keys[$key] = $value;
        }
        
        public function 
    get($key)
        {
            if (
    $this->isValid($key))
            {
                return 
    self::$keys[$key];
            }
            else return 
    false;
        }

        public function 
    isValid($key)
        {
            return isset(
    self::$keys[$key]);
        }

    Hmm...

    Any thoughts? Should I stop worrying about swaying toward testing a specific mechanism and just make a file? Still a cache though right? Even if only for the duration of the script and only stored in memory.

  23. #23
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    I was actually hoping the file cache might be what you chose as the simplest way to pass the test.

    If you implement the file cache, and run the tests twice, you will actually have a failure becuase the key should will already exist from the prior run. This will lead us towards using the setup() and teardown() features of xUnit tests. Take a stab at coding the file based cache and see if you see the effect.
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.

  24. #24
    Resident Code Monkey Chris Corbyn's Avatar
    Join Date
    Nov 2005
    Location
    Melbourne, Australia
    Posts
    713
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hehe I see what you're getting at

    I'm going to bed now as it's past 1am. I'll post the FileCache version tomorrow.

    Thanks for the hand-holding so far

    EDIT | Is it my imagination or is pagination not working in this thread?

  25. #25
    eschew sesquipedalians silver trophy sweatje's Avatar
    Join Date
    Jun 2003
    Location
    Iowa, USA
    Posts
    3,749
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Pagination will work fine once you get past 25 replies
    Jason Sweat ZCE - jsweat_php@yahoo.com
    Book: PHP Patterns
    Good Stuff: SimpleTest PHPUnit FireFox ADOdb YUI
    Detestable (adjective): software that isn't testable.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •