August 28, 2008

ZenMagick unit testing

Tags: ,
Filed under: ZenMagick — DerManoMann @ 1:22 am

With ZenMagick 0.9.2 there is now an easy way to do automated testing.
The new zm_tests plugin comes with a number of tests that make sure that things do not get out of hand and to keep regressions low.

All testing is done in your browser and for those of you using IE, here is a screenshot of what you are missing out on :)

Web based testing

Web based testing

(I will try to improve the layout across browsers, but it’s a very low priority as it is working fine for me ;)

Edit: Actually, fixing the validation errors and generally making the page look a bit cooler helped a lot! This means the current trunk version does look good in IE, too.

Tests are grouped based based on the directory the code is found in (one level only) and it is easy to select and run single tests, a particular group or all.

Looking at the image you can also see the group ‘@other’. Tests in that group do not come with the plugin but are tests written for other plugins.

The way it works, plugins can detect if the testing plugin is installed. If so, they are able to programmatically register new tests. That means everyone can use the testing framework to easily run their own tests.

So far the most important tests are possibly the price calculation tests. Those actually depend on the demo store data being available in the database, as at least attribute prices are compared to static data. I might be able to change that in the future, but that will involve some more digging into zen-cart code.

Unit tests are written using the great SimpleTests library. The main reasons I picked that particular one were:

  • Easy to compress into a single file
  • Web page testing out of the box
  • Comes with a basic HTML report module

To be honest, other unit testing projects might provide the same, but after a few trials simple tests just fitted best into ZenMagick.

Expect more tests coming – I made a point of writing tests for most of the changes for 0.9.2. There will be more, in particular I plan to convert the included JMeter configuration into unit tests. There are a couple advantages in doing that:

  • Single interface for all testing
  • No other software required other than a browser
  • Tests can incorporate brower actions plus database verification at the same time

I apologize if I do not use some of simple test’s unique features like autorun, but it seems a lot nicer this way :)

Finally, a simple example of how to write a new test:

  1. Create a new file with a class extending UnitTestCase:
    class TestSimpleResultList extends UnitTestCase {
    ...
    }
  2. Add a method that starts with ‘test‘:
    public function testSomething() {
    $this->assertTrue(1 == 1);
    }
  3. Drop that new file in zenmagick/plugins/request/zm_tests/tests/misc

To use code to add a test (for another plugin), the following could be used in the plugins init() method::

if (null != ($tests = ZMPlugins::instance()->getPluginForId('zm_tests'))) {
// add class path only now to avoid errors due to missing UnitTestCase
ZMLoader::instance()->addPath($this->getPluginDir().'tests/');
$tests->addTest('TestZMTokens');
}

improving ZMDatabase

Tags:
Filed under: ZenMagick — DerManoMann @ 12:26 am

With 0.9.2 out of the way, I’ll be back to improving the ZenMagick database layer.

The new release fixes a lot of stuff and adds quite a few handy things, but there are also still gaps that mean it can’t be used everywhere.

Also, it still doesn’t work well with the zm_phpbb plugin, as the switch between databases is not handled properly.
The next thing, though, is to get clean up the mapping file, so that there are no duplicate field names any more. This is actually not so much a bug, but a something that can cause problems with the way the zen-cart tables are arranged. What happens is that joins and such will cause columns with the same name being read from different tables. The result is that there is no predictable (at least not easily) way to tell which one will *win* and be the one in the model class. Making sure that fields are mapped to different properties should help.

Another problem is the way that all primary keys are mapped to ‘id’. While this seemed a good idea as far as the API is concerned, it suffers from the same isses as oulined above. In particular the attribute related queries did create some regressions as the wrong ‘id’ was used… (That is also the reason why all attribute price tests currently do fail).

Luckily, with the magic get/set methods in ZMModel that should be easily fixed.

August 26, 2008

toolbarmode 0.7.5

Filed under: Mozilla — DerManoMann @ 11:36 am

I finally managed to find the time to update toolbarmode again. Beside some new translations – thanks BabelZilla! – it’s now configured to properly install in FF3.

Since I didn’t find the time yet to implement the stuff required to get it accepted at AMO, you’ll have to download/install from this site, though.

Sorry for the long wait,

mano

August 19, 2008

downloads and visibility

Tags: ,
Filed under: ZenMagick — DerManoMann @ 5:30 am

With the return (not yet complete) of the sourceforge stats it’s interesting to see the download numbers of the last couple releases. Also, the ZenMagick downloads on the zen-cart site do grow (about 500 AFAICT).

At sourceforge, in particular the number of downloads of the apidocs has surprised me a bit, considering that everything is available online. Maybe the work I put into the source code documentation is slowly paying off.

It would be nice to see more of the downloads converted into actual live sites using ZenMagick, but I guess that most software has a high percentage of downloads that get evaluated and then dismissed.

it’s nice to see that the time and work I put into this project do not get ignored completely ;)

Despite that there is probably more to be done. One aspect of managing a project like ZenMagick that I have mostly ignored so far is marketing. I even have had a few people *complain* that they found ZenMagick only *after* spending a lot of time trying to get their design working in zen-cart and were suggesting that making  ZenMagick more visible  might be a good idea.

However, I am abit at a loss here. As an Open Source project, I do not have a budget (even though I have received a few donations) not the whish for traditional advertisement. Also, I guess I wounldn’t have a clue as to what to do anyway.

What I could imagine, though, is an approach that would be more in line with the spirit of Open Source projects and that would be a community effort to make ZenMagick more popular.
Now, don’t get me wrong. I do realize that there isn’t that much of a community (yet), but, as pointed out above, things do seem to improve. The frequency of forum posts is growing, the number of downloads is going up and the stats of this blog also indicate more interest.

So, what I imagine could help would be for you to:

  • Dig or bookmark ZenMagick with your favorite bookmarking service
  • Write about ZenMagick and your experiences
  • Post reviews (even negative ones, as I usually learn more from those)
  • Keep a ‘Powered by’ link in your finished store to let people find out what software you are using

Having more sites using ZenMagick would, of course, be good for me.  Although, it would also be good for the users, because:

  • bugs do get found a lot faster
  • more features will be requested (and hopefully implemented)
  • more themes/plugins would be available
  • things would just be better :)

I’ll leave it to you to come up with more ideas. Advertising on the zen-cart website seems, unfortunately, out of the question ;)

mano

August 18, 2008

themes

Tags: ,
Filed under: ZenMagick — DerManoMann @ 10:38 pm

Good news for people looking for ZenMagick themes. According to this forum thread there is going to be a free SilverFish theme for ZenMagick. However, no ETA and it might be some time a good thing!

inspired by that I have also started creating a new theme. It won’t be ready for 0.9.2, but should be finished shortly after.

August 7, 2008

form handling

Filed under: ZenMagick — DerManoMann @ 11:19 pm

I just added another item to my tasklist for 1.0.0. It’s about using model classes and objects to populate forms.

Generally this works quite well, but every now and then there is this ugly exception that makes it very hard to use.
Perhaps the most famous example of those exceptions is the date of birth field in the create/edit account forms. There have been several attempts at fixing this, usually by changing the way dates are converted and formatted. However, those changes do not take into account the real issue: the date format in the model class and the format in the form do not match.

Well, you might say this is all taken care of by converting the input in the populate() method of ZMAccount and by using $locale->shortDate() in the template.

Unfortunately, this leaves out the most critical case: an invalid date. If that happens, the invalid date gets converted into the internal format and then back to the presentation format. Usually, the result is not very nice to look at. Another issue is that the validation will look at the actual input, rather than the converted value in the model.

So, it looks like there have to be some more classes to decouple that.

One benefit could be that the validation could change to work entirely on those objects rather than the raw input. This could also make it easier to push feedback out of the validation process.

On the other hand some validation might depend on the custom processing that is currently done in the populate method of some model classes, even though I think that this is actually bad design rather than a feature.

I have a few ideas I’ll be playing with and some might actually work without template changes which would be a good thing.

it’s a plugin!

Filed under: ZenMagick — DerManoMann @ 4:33 am

I am trying hard to have at least one new single plugin per release. Even though there is going to be a new plugin to run unit tests I decided that that was not enough!

I’ve been looking at the automatic login mod a bit and thought this might be a good candidate to start using the new events that have introduced in the last few releases.
What can I say – it was as easy as I expected it to be :) A single file plugin does all the work. And even better, it will automatically log you in on any page (including the proper redirect).

So, expect this to be available together with the next release.

August 5, 2008

newsletter subscribe

Filed under: ZenMagick — DerManoMann @ 1:02 am

A while ago I implemented the missing newsletter subscribe controller. Quite interesting that no-one noticed the absence so far :?

One thing that is still missing is support for unsubscribing directly via a GET parameter. First, I thought this wasn’t necessary as it is rather simple to just login and use the account option to unsubscribe.

However, I suspect that th main reason is to allow unsubscribe links in (newsletter) emails, so people can unsubscribe right away.

To mitigate this, there is a new setting to allow anonymous unsubscribe. What happens is that the unsubscribe view will either refer the user to the account area, or, if configured, show an unsubscribe form.

The only issue I do have with this is that it allows anyone to (potentially) unsubscribe other email addresses (leaving, for a moment,  aside the issues around having proper opt-in and opt-out).

What I would like to see is a system of one way hashes that can be retrieved via a service class and attached to URLs. They would then be used to verify the email address.

Additional *features* could be that they could expire to make abuse even less liklely.
Another idea would be that they are *bound* to a resource (read: a string). In the newsletter context this would be an email, but this could also be an order number, an account id, etc.

So, for example, an infividual hash would be valid only if it gets validated together with the resource it is bound to. Here, the unsubscribe controller would have both the email address and the token in the URL, so could both use to verify that the token is valid.

Once the unsubscribe is done, the token is invalidated and can never be used again.

To avoid having to add all this to core, I could imagine a plugin that could offer this sort of service. Code that wants to use it (potentially) could use some sort of generic service lookup to find out if the serivice exists. If not available, there should be fallback options about whether or not this is still ok.

The lookup could be a public version of ZMObject::singleton($name); perhaps in ZMRuntime.

Comments, suggestions or any reaction whatsoever appreciated…

sourceforge stats

Tags:
Filed under: General, ZenMagick — DerManoMann @ 12:45 am

It seems sourforge finally gets the project stats back online. I had a working page just a moment ago – mind you, proper graphs, just no data ;)

However, now the page is back to the depressing ‘Error fetching statistics data‘ message. Oh, well, a bit more patience and everything will be ok, right?

file permissions

Tags: ,
Filed under: ZenMagick — DerManoMann @ 12:42 am

One of the things that ZenMagick does not very well at the moment is handling file permissions of files it creates.

I just added this on my 1.0.0 tasklist, so hopefully it should get better soon.

Until then, there is a simple workaround – using the PHP Console that comes with ZenMagick (admin: ZenMagick -> Console.

The following shows the most useful commands for handling permissions.

getcwd();

Returns the current working directory. In the console context, this is going to be the full path to the admin folder: This is helpful to get your bearings.

chmod(..);

Another PHP function to change file permissions. For example, the following will grant full file permissions to everyone (user/group/other) to init.php:

chmod(getcwd().'/../zenmagick/init.php', 0777);

ZMTools::rmdir(..);

A very dangerous function that allows to recursively delete a folder tree incl. any containing files. To, say, delete an empty theme the following could be used:

ZMTools::rmdir(getcwd().’/../zenmagick/themes/MyTheme’);

Even though I used getcwd() in the examples to build the filename/directory name, it is worth using proper full names to minimize the chance of deleting anything accidentally.