Programming with JMeter-- Sampler and Listeners

        完成JMeterEngine, ThreadGroup 和 JMeterThread的整合,外围的设施差不多搞定大半了,接下来是把具体的测试逻辑整合进来,既然是框架层面的,需要通用一点,方便客户端自己定义测试逻辑。不过在此之前,还需要研究下Sampler和Listeners,这样对JMeter的整个流程会有全局的把握。先看下图:

Programming with JMeter-- Sampler and Listeners       SampleListener和TestStateListener作为很重要的两个Listener贯穿了JMeter整个test的生命周期。

       先看TestStateListener,两个方法名就能让我们猜到作用:

1) 在测试开始时候调用 testStarted

2)    在测试结束的时候调用testEnded    

      

       这些生命周期函数的调用是在什么地方呢?这个又要回到JMeterEngine了,看StandardJMeterEngine#run()方法,在启动ThreadGroup之前以及整个测试结束之后,代码是这样的:

public void run(){
        。。。。。。
        SearchByClass<TestStateListener> testListeners = new SearchByClass<TestStateListener>(TestStateListener.class); // TL - S&E
        test.traverse(testListeners);

        // Merge in any additional test listeners
        // currently only used by the function parser
        testListeners.getSearchResults().addAll(testList);
        testList.clear(); // no longer needed

        if (!startListenersLater ) { notifyTestListenersOfStart(testListeners); }
        test.traverse(new TurnElementsOn());
        if (startListenersLater) { notifyTestListenersOfStart(testListeners); }
        。。。。。。

        ////此处省略 n 行代码
 
        。。。。。。

       notifyTestListenersOfEnd(testListeners);        
}

          代码解释如下:

          1) 从HashTree中找出所有TestStateListener类型

          2) 在测试正式开始之前,触发这些TestStateListener,notifyTestListenersOfStart(testListeners)这个方法中会调用testListener#testStarted方法

          3) 在测试执行完之后,再触发这些TestStateListener,notifyTestListenersOfEnd(testListeners)这个方法会调用testListener#testEnded方法

           理解了这些,来看看具体三种我们会用到TestStateListener(如上面类图):TestPlan,JavaSampler,RresultCollector,看看他们的testStarted()分别做些什么

 1. TestPlan:主要设置一些文件路径,方便查找config, log等文件,不需要再去干预。

 2. JavaSampler: 主要是加载client类,类名是根据HashTree中的配置数据。这个比较重要,因为这里是整合测试逻辑的地方,看下代码

               

@Override
    public void testStarted() {
        log.debug(whoAmI() + "\ttestStarted");
        initClass();
    }

private void initClass() {
        String name = getClassname().trim();
        try {
            javaClass = Class.forName(name, false, Thread.currentThread().getContextClassLoader());
            Method method = javaClass.getMethod("teardownTest", new Class[]{JavaSamplerContext.class});
            isToBeRegistered = !method.getDeclaringClass().equals(AbstractJavaSamplerClient.class);
            log.info("Created class: " + name + ". Uses tearDownTest: " + isToBeRegistered);
        } catch (Exception e) {
            log.error(whoAmI() + "\tException initialising: " + name, e);
        }
        
    }

/**
     * Gets the Classname attribute of the JavaConfig object
     *
     * @return the Classname value
     */
    public String getClassname() {
        return getPropertyAsString(CLASSNAME);
    }
 3) ResultCollector:主要是初始化File Output,做好写测试结果的准备。代码如下:

相关推荐