The intersection of technology and leadership

Category: Development (Page 7 of 18)

Poka-Yoke Your Developers

Poka-Yoke is a term coming from lean manufacturing and is about error-proofing, or preventing an error happening in the first place. A few weeks ago, we were working on fixing those flaky tests. A cause is the bad testing strategy, trying to set mocks on objects held by spring globaltons.

The previous developers had apparently known about this and went through diligently fixing each tests by ensuring that any test setting a mock was reset to its proper form. Unfortunately this knowledge wasn’t passed on to our team, and wasn’t obvious from the intent of the tests. More than that, it was easy to add new tests of this style and forget to reset the objects registered in spring.

Wanting to apply Poka-Yoka to our situation, we wrote something that would check the precondition that there were no side effects from other tests. Our implementation meant adding a @Before method to the base class these classes all shared that would cycle through all objects registered in spring, noting if any of their internal fields had been left mocked. If anything was detected, our assertion failed message contained a message that would explain why it was there and what to do about it. By adding this in, we actually found three existing tests that failed to clean up properly after themselves.

Poka-Yoka is fairly easy. When thinking about applying it, think about a solution that prevents the error happening more than once. Ideally this means that error is unavoidable (in our situation – this would mean changing the testing pattern across all tests), or at least by bare minimum, provide feedback when a person repeats the mistake.

Ruby Script to Capture HTTP traffic

I spent some time early this week trying to debug why some test was failing. It was using RESTeasy and I wanted to find out exactly what HTTP packets it was sending. If I was on a windows machine, I’d look towards Fiddler, but I couldn’t find anything easy on mac, so I wrote a little ruby script that I could point the client at and dump out all headers and request body.

It looks like this:

require 'webrick'
include WEBrick

class Simple < WEBrick::HTTPServlet::AbstractServlet
  def do_POST(request, response)
    puts "Body: " + request.body
    puts "Header: " + request.raw_header.to_s

    response.status = 200
  end
end

server = HTTPServer.new(:Port => 5899)
server.mount "/", Simple

['TERM', 'INT'].each do |signal|
trap(signal){ server.shutdown }
end

server.start

Update
Upon publishing this, I got a couple of alternatives worth looking into for next time.

  • Jim suggested using tcptrace; and
  • Gaz suggested using the following command sudo tcpdump -vvv -A -s 0 -i en1 tcp ‘port 5899’

This is just yet another example about why it’s important to have diversity when problem solving. I didn’t even know about these tools. Now I do and you do too.

Three Days of Clojure Joy

A couple of weeks ago, I sat in a training class run by Stuart Halloway, CEO of Relevance and who ThoughtWorks happened to bring across from the US to give us the low down of Clojure.

We covered a lot of material in the three days – covering pretty much every aspect of Clojure. We learnt all the basics such as core data types, namespaces, how to get documentation and examples, and many of the key functions that come as part of the core clojure libriares.

I appreciated the time spent discussing the background of why clojure exists, and the alternatives that are present in many other languages. It was great to have someone as knowledge as Stuart as we could ask as many questions as we like about things.

The training wasn’t just all talking and we did do a few exercises. I have to admit because I hadn’t touched any real functional programming since university, many of the exercises towards the end of the three days went over my head a little bit – a combination of needing to know some key clojure functions, and probably needing to re-adjust to a “functional way of thinking” which I think proves the biggest challenge.

In terms of tooling, we used the simple REPL and whatever environment we chose (the exercises don’t really need that much) although I learned about ParEdit that seemed to be quite useful.

I also learned about a new datastructure – Bit Partitioned Hash Trees (more here and here that I need to do some more reading around.

The course accelerated quickly, covering basic functional programming on the first day, the different ideas between state and time in clojure and then syntatic programming. Also we covered topics such as Interoperability with Java libraries and the problems that protocols address and defrecords (prefer defrecords over deftypes as the latter is now considered deprecated).

Just like any good training course, it left me realising how much more I need to learn and get my head around. This only really comes with more time and practice.

Beware the Spring Globaltons In Integration Tests

As I mentioned in a previous post, we’ve ben trying to fix a whole slew of tests that flicker, and we’ve spent some time fixing a number of integration tests that leave side effects.

This is the first time I’ve encountered the testing pattern (not recommended!) where SpringJUnit4ClassRunner loads up a spring context, a bean is pulled out, and then mocks used to stub out services. It’s a really evil pattern.

For one thing, mocks are about interaction based testing, not really about stubbing. I typically use them to drive out class-based roles. However, in this case, they were used to take out a portion of the application.

Using the above JUnit Runner means that there is one spring context per test run, effectively, a global pool of objects. Of course, when you pull one out and start modifying the objects, it means you have plenty of side effects across other tests. Unfortunately the don’t always manifest themselves in obvious manners.

Our solution to fix this was to use reflection to look at all beans in the spring context, and fail the test if it found any that had any mocked instances. I’d still recommend you avoid the testing pattern altogether, but if you are forced down this route, you now have a solution to detect side-effects across tests.

Finding real object under spring proxies

As part of detecting side effects across tests, we needed to inspect some objects in tests autowired by spring. Unfortunately these objects were automatically proxied with the current configuration (and needed by some tests) so we needed some way of accessing the underlying proxied objects.

We didn’t really find many good examples of how to go about bypassing the spring proxies created through AOP. Doing a bit of debugging we found that spring used CGLib to generate its proxies and there is fortunately a method made accessible called getTargetSource() that gives you the underlying object. Here’s the helper class we wrote to extract it.

public class CglibHelper {
    private final Object proxied;

    public CglibHelper(Object proxied) {
        this.proxied = proxied;
    }

    public Object getTargetObject() {
        String name = proxied.getClass().getName();
        if (name.toLowerCase().contains("cglib")) {
            return extractTargetObject(proxied);
        }
        return proxied;
    }

    private Object extractTargetObject(Object proxied) {
        try {
            return findSpringTargetSource(proxied).getTarget();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private TargetSource findSpringTargetSource(Object proxied) {
        Method[] methods = proxied.getClass().getDeclaredMethods();
        Method targetSourceMethod = findTargetSourceMethod(methods);
        targetSourceMethod.setAccessible(true);
        try {
            return (TargetSource)targetSourceMethod.invoke(proxied);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private Method findTargetSourceMethod(Method[] methods) {
        for (Method method : methods) {
            if (method.getName().endsWith("getTargetSource")) {
                return method;
            }
        }
        throw new IllegalStateException(
                "Could not find target source method on proxied object [" 
                        + proxied.getClass() + "]");
    }
}

Clearing In-Memory Messages held in ActiveMQ

One of the major troubles with integration tests are the tradeoffs you get with speed and feedback. As systems get larger, the more integration tests you have, and the more chance you might preserve state. I’ve been fighting a build inherited by our team where intermittent integration tests prove troublesome. In the next series of posts, I’ll detail some of the issues we’ve found and some of the fixes.

Our current system uses JMS for messaging and one of the first stateful problems we found were messages being left over from previous test runs in our ActiveMQ instance. We had a few options for doing it out of memory including a purge script and a call to deleteAllMessages though the latter failed because we stored messages only in memory.

Instead we worked out how it stores messages, and wrote a class to go through and clean them all up.

public class ActiveMqHelper {

    public void removeAllMessages() {
        Map<String,BrokerService> brokers = BrokerRegistry
                .getInstance().getBrokers();
        try {
            for (BrokerService brokerService : brokers.values()) {
                Broker broker = brokerService.getBroker();
                new ActiveMQBrokerExtension(broker).clearAllMessages();
            }
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    private class ActiveMQBrokerExtension {
        private final Broker broker;

        public ActiveMQBrokerExtension(Broker broker) {
            this.broker = broker;
        }

        public void clearAllMessages() throws Exception {
            Map<ActiveMQDestination, Destination> destinationMap 
                = broker.getDestinationMap();
            for (Destination destination : destinationMap.values()) {
                ActiveMQDestination activeMQDestination 
                        = destination.getActiveMQDestination();
                if (activeMQDestination.isTopic()) {
                    clearAllMessages((Topic)destination);
                } else if (activeMQDestination.isQueue()) {
                    clearAllMessages((Queue) destination);
                }
            }
        }

        private void clearAllMessages(Topic topic) throws IOException {
            List<Subscription> consumers = topic.getConsumers();
            for (Subscription consumer : consumers) {
                ConnectionContext consumerContext = consumer.getContext();
                MessageStore messageStore = topic.getMessageStore();
                messageStore.removeAllMessages(consumerContext);
            }
        }
        private void clearAllMessages(Queue queue) throws Exception {
            queue.purge();
        }
    }
}

Someone might one day benefit from this.

Testing Pattern: Exploratory API via the Web

Last year I was working with Tiest, a former colleague of mine at a bank working on a system with an internal API. It was quite an experience, though I will save that for another (set of?) blog posts for another time. The application was centrally hosted with a client API that allowed people to interact with the server side. The testers needed something to help them do more exploratory testing and my former colleague came up with a great solution to this problem that I thought would be worth recording here for posterity.

Our solution had these characteristics:

  • Provided through a web browser – Installing items onto the testers machines became a bit laborious, namely because they didn’t have rights to install, change or run anything with administrator privileges. It was easier to deploy the tool centrally, and then let the testers prod from afar. This was as simple as writing a page that submitted some code to a web server, that than executed it and returned the results back to the client.
  • Supported dynamic execution – We could have written a web layer on top of the client API but we didn’t really want to add another layer for maintenance. We simply used the javax.script package to turn our standard POJOs into a scriptable/dynamically invokable system.
  • Built in reflection functions – Using the scripting interface meant that the server would not store any state. So the server had a number of built in functions such as a listAll(object) that would show all available property/methods to the user
  • Example queries stored on a wiki – When a tester would ask for something to be checked against the test environment, I would convert it into an appropriate query they could paste into the query browser window. They could then execute it, tweaking parameters, etc and learn to compose things. They didn’t have to really understand how java (as script) worked, just build on what was there.

Although I won’t be reaching into my testing patterns toolkit for this pattern too often, I feel it worked well to enable our non-technical testers to get at something given a number of environmental constraints.

« Older posts Newer posts »

© 2024 patkua@work

Theme by Anders NorenUp ↑