OU blog

Personal Blogs

New blog post

Visible to anyone in the world
Edited by Sam Marshall, Friday, 21 May 2010, 22:58

Here's an update on what we've been coding recently in the area of the OU where I work! I've done a few things, some of which may be of interest to other Moodle users, others not so much.

  • I fixed final glitches etc. in the courses dashboard for tutors (mentioned before; it uses a webservice to access information from our Moodle system, and other systems, about which forums a tutor can access across all courses and whether they contain unread messages, then displays all these links in one place for convenient access).
  • I wrote a block for the glossary in Moodle 2. Teachers can add this block to a glossary then use it to search all the other glossaries they can access. The idea is, if they want a glossary entry about something for a course they're writing, they can search all other courses to see if somebody already wrote one. I'd love if people try it out (and I'd love even more if you can manage to convince the Moodle HQ folk that it should be included in core Moodle).
    There will be a version of this feature in OU Moodle 1.9, but I haven't written that version yet. This development was part of our current project to learn more about coding for Moodle 2.0, which several developers here are involved in as we work out how to plan for a possible upgrade of our systems. Coding in Moodle 2 is definitely nicer than in 1.9, so I hope we can go ahead with it...
  • I updated the Java audio recording applet I have, which is designed for students to record themselves. It's basically just to save them having to download a standalone application; everything it does is local. Anyway, it now looks nicer (we didn't have graphic design resource, but I tidied it up based on the upcoming new OU styles that were already designed) and a few usability glitches have been ironed out. The applet's open source; you can get the code here, or try it out on this temporary prototype site. Assuming we don't find any horrible problems with it, this will be used to replace the current Audio Recording Tool for Languages courses.
  • I added support for .mp4 in more places in OU Moodle (it was already supported in some places). We're transitioning from .flv. Now we're going to be fully ready for the .mp4 video format just in time for it to become obsolete. Awesome!
  • Thanks to the current round of testing from our Technical Testing team, I fixed lots and lots of bugs in OU Moodle (for our June releases) including some in our publicly-available modules (ForumNG, OU wiki) and just a couple in core Moodle 1.9 and 2.0 as well.

I've done some other things in the last couple of weeks too, but I think I'll stop there; this is supposed to just give you an idea, not to be an exhaustive list... sorry about that! However, I should also mention the others on my team:

  • Ray has nearly finished auto-archiving for ForumNG. The idea is you can set forums to automatically delete discussions when they're inactive for a number of months. If you prefer, you can also make it move the discussions to another forum (presumably a hidden 'archive forum' or something). This means that very busy, very long-running forums won't eat up too much database space and won't reduce in performance as the number of discussions climbs into many thousands.
  • Mahmoud has nearly finished advanced search for ForumNG. In addition to the existing free-text search (powered by the ousearch block), you can search by date or by user (full name, partial name, or username).

I hope we'll do the public 'stable version' ForumNG release in a couple of weeks (shortly after the OU's update on June 1st). The idea is that this will be maintained in line with the fully-tested OU updates, rather than getting every new (and possibly broken) feature as soon as we finish it. So it won't have the two features mentioned above, but it should be useful if you want to run ForumNG on a major site.

Finally, a side note: I just bought a tune called Theme From HTML (Steve Hill & Technikal; Dark by Design mix; on Masif). Playing it now. It's very ugly indeed. If you imagine the 4:4 kick/snare is your head and the bassline is a brick wall, it sounds just like coding HTML for Internet Explorer! Awesome.

Permalink
Share post

Unit testing opinions

Visible to anyone in the world

Tim dumped a huge book about unit testing on my desk today. He thinks I should read some of it!

But I'd been thinking of writing a blog post about unit testing, so why not take the opportunity before I read too much of the big book and it spoils me? I'll try to write a blog post that's nearly as long as the book!

First if anyone doesn't know what unit testing is, (a) it's a technique for writing computer program code that tests other pieces of computer program code in an automatic, repeatable way so that if you change the code that's being tested, and the change breaks something, the test will probably start to fail and you'll notice... and (b) you probably don't care about this post. Go have fun somewhere else! This is about boring programming stuff.

In my recent personal projects I do significant unit testing, but I don't really follow any of the buzzwords. Here's what I think, divided into neat pairs (spot the odd one out).

Be careful - I'm going to say that you 'should' do something or that you 'must' do something else or that 'nobody' would be stupid enough to even go within bargepole-reach of the general concept of a third something. If that's likely to concern you, please just pretend I said 'in my opinion' several times per sentence.

Is unit testing worthwhile?

  • Unit testing is really, really important when writing complex backend code. Unit testing won't work for UI code. This means you should ensure that as much code as possible is in the backend. But you know that already.
    Without unit tests you cannot change anything without being desperately panicky about whether it'll break (and it probably will). If you're doing something complicated you definitely want unit tests.
    JUnit is integrated into Eclipse, so if you're a Java programmer, it's easy to get started and run tests. No need to create test suites or anything. Just right-click on a source folder containing Java files with JUnit tests and 'Run As... JUnit Test' to run 'em all.
  • If you're doing something simple, writing unit tests is a waste of time. Don't bother. Unit testing set/get pairs - or anything that basically boils down to that - isn't big and it isn't clever. Because Java's a compiled language and because modern compilers give warnings for things like assigning variables to themselves, the chances you would break any code that simple are pretty damn low.

How completely should you test? At what level should you test?

  • When testing complex code you've written, coverage is important. Test coverage means the instructions that were covered by all your test cases. You hit run on all your test cases and something tells you what percentage of code was covered.
    If a branch wasn't covered by the test cases, it's probably a good bet that it's broken, so getting good coverage is important. I'd guess you want to be at least 80% or so, with maybe just some error cases and set/get and suchlike omitted. (If the errors are really important, i.e. might actually happen for somebody whose machine isn't already terminally broken, then you should make those tested too.)
    For Java developers, coverage testing is easy. Just install the EclEmma Eclipse plugin. It'll show you coverage by package tree, and you can look at source files to see lines that were covered (green) and weren't (red).
  • So I think coverage is important. But I don't think it matters a damn where that comes from. You do not need a matching test class for every real class. If you write low-level classes which are used by higher-level ones, then fine - just do tests for the higher-level ones, provided that gives reasonable coverage (and finesse the inputs to the higher-level code so it does). Or do lower-level tests for the worst most fiendish parts of that code, but don't bother with the finicky details; leave that for the higher-level stuff that will use it.
    Some people argue this means you can't immediately tell what failed. They're right, but nobody cares. Unless you're writing the world's most complicated project, it's unlikely that a failure in a high-level test would be more than a matter of minutes to track down at a lower level. You have a built-in reproducible example right there, and you know how to use the debugger. THERE IS NO STEP THREE. Come on. (Plus, you have the clue it's probably related to, oh I dunno, maybe something in the checkin that broke the unit tests?)

What about writing test code itself?

  • Test code should be well-organised so that we know which class you're testing...
  • ...but it doesn't have to be good quality code. Who cares? It's test code. Stick some comments in if you're doing something non-obvious or if you feel like it but if you have a function called testFreeble and your system has a feature called freebles and you run the freeble() function 3 times inside that test... I think we know what you're testing. If you call a function with -1 or 0 then it's probably an out of bounds or edge case. We get it.
    Similarly, refactor stuff (using the automatic 'extract method' or manual refactoring) to make your life easier writing and updating tests, but not purely for code quality reasons. Nobody needs to read tests unless they break. Unless your 'real' code is already perfect, spend time improving that before you waste it on test cases, which are usually relatively simple.
    Maybe you've configured your Java compiler to give a warning if you write a public method without javadoc (I do) - you can turn this off in test code because all test methods are public and those 'Tests freebles' comments get really old really fast. @SuppressWarnings("all").

Do you write tests before or after development?

  • After. Puh-leeze. You know you're going to change the API. How boring would a project be if you knew what the API was going to be before you started? And unit tests, achieving coverage, are not black-box tests; your test manipulates a black-box, but when writing the test, you choose test cases based on what you know's inside. It's much easier to do that when you've written it.
  • But, ideally, straight after. Write the complicated back-end code for the project first. You haven't got a user interface to run it - so until your project's very near finished, literally the only way you should ever be running it is through hitting 'play' on the JUnit view.
    Once you finish a feature, do the test for it. Running that test, you know your code won't work, because it's the first time it's ever been run. Yay! That's a good thing. Because writing tests is much less tedious if there's some realistic chance, like in this case about 90%, that they actually fail initially, and you have to go off and fix the bugs in your actual code.

Testing in Java is a dream; 'existing horrible project' aside, there's really little excuse not to do it. Write everything complicated as a separate backend package and test that sucker before you glue it into a real projet. Everything runs at lightning speed, you've got all the nice, pretty tools built into the IDE you already use (by the way, if you prefer NetBeans, the tools are available in that too).

 

Sooo.. at work I mainly have to develop things for (our customisation of) Moodle, which is written in PHP. Aaaand we're off to a flying disaster right there...

Moodle uses SimpleTest, which is a perfectly okay framework, but suddenly I have to go to a webpage to run the tests instead of hitting Command-F11. At present there isn't coverage stuff in it, either. We can never get the debugger to work (that's okay, I can live with print_object). But worst of all, everything in Moodle is tightly integrated, and (this part isn't really Moodle's fault) most of the complicated bits which are likely to break are actually database queries. Which means you can't usefully test it by abstracting out the database, even if that wasn't an absolute nightmare that wastes hours of development time (and yes I've done it).

Moodle 2 provides some things to make testing fractionally easier but overall it's still a nightmare and will remain so until there's some solution for setting up a reliable test database each test without having to do any work. (I favour SQLite or similar.)

In Moodle 1.9 frankly I can only be bothered to do unit tests where really essential (e.g. I did a fix for a bug with the shorten_text function, which is a complete nightmare, so I needed a test to have some confidence in my fix not breaking everything). The rest of the time... meh. Yes, that definitely makes my code less reliable, but with our timescales and the difficulty of unit testing, I don't see any option.

OK so that was way too long; if you read this far, have a cookie. (No, I didn't bring any cookies! Supply your own. Sorry.) Still, that's what I currently think about unit tests, not being an expert but having done or attempted them for quite a while. Let's see if I change my mind after reading Tim's book! (Which by the way is 'XUnit Test Patterns')

Permalink 1 comment (latest comment by Tim Hunt, Tuesday, 20 Oct 2009, 09:35)
Share post

This blog might contain posts that are only visible to logged-in users, or where only logged-in users can comment. If you have an account on the system, please log in for full access.

Total visits to this blog: 245933