FIELD NOTES / WLDANDAN

Happy Coding, Happy Life

Systems, software & the craft of making things work.

EST.
2013

INDEX / TEST

Test

· Test

Page Object Understanding

##什么是Page Object Page Object是Selenium中提出的一种测试设计模式。在Web前端自动化测试的过程中,Page Object可以称得上是居家必备的良品之一。PageObject将与Web测试页面交互的行为封装在其内部,旨在将每个页面或者相似页面的功能封装,例如页面中需要测试的元素(按钮,输入框,标题等),这样,通过在测试中访问Page类的相应方法来获取页面相应的元素,从而巧妙的避免了当页面元素id或者位置变化时,需要修改测试代码的情况。

言而总之,总而言之,PageObject就是将Web页面元素的变化封装起来,提供API供外部测试代码调用,从而达到将测试代码于Web页面元素的变化解耦。

· Test

Mockito - Partial Mock

Mockito是一个方便的java测试Mock工具。

当我们做TDD或者单元测试的时候,为了消除当前被测对象和其依赖之间的关系,经常使用Mockito。

本篇文章只涉及如何使用Mockito的Partial Mock。关于Mockito的其他用法,请参照Mockito

###1. 什么是Partial Mock 在单元测试的过程中,偶尔会出现这种情况。对于一个对象,某些方法需要被mock,而某些方法希望被直接调用,这时候,我们就需要借助Partial Mock。

###2. 使用Partial Mock的场景

在如下两种场景中,Partial Mock就显得相当犀利:

a) 测试存在具体方法的抽象类

public abstract class AbstractHandler {

    public String greet() {
        return "Hello " + fetchName() + "!";
    }
 
    protected abstract String fetchName();
}

如上代码所示,抽象类AbstractHandler中定义了方法greet(),并且该方法存在一定逻辑。 此时,如果希望测试greet(),可以选择两种方式:

  • 构建其派生非抽象类,如ConcertHandler,再进行测试。
  • 使用Partial Mock,它可以省去构建派生类的步骤,直接对该抽象类进行测试,代码如下所示:
public class AbstractHandlerTest {
		
    @Test
    public void shouldCallRealMethodsAndFakeAbstractMethod() {
        AbstractHandler handler = mock(AbstractHandler.class);

        when(handler.greet()).thenCallRealMethod(); 
        when(handler.fetchName()).thenReturn("Geek");

        assertThat(handler.greet(), is("Hello Geek!"));
    }
}

如代码所示,对于抽象方法fechName(),直接mock其返回值 when(handler.fetchName()).thenReturn(“Geek”);

对于被测方法greet(),则使用thenCallRealMethod()使Mock对象调用真实的实现方法。 when(handler.greet()).thenCallRealMethod();

b)测试过分依赖于I/O操作的类


public class BooksController {

    protected Map<String, Date> fetchBooks(){
        //fetch the books from different publishing company.
        service1.retrieveBooks();
        service2.retrieveBooks();
        ......
        service10.retrieveBooks();

    }

    protected List<String> getPublishedBooks(){

        books = fetchBooks();
        //only pick up the books published.
    }
}

如上代码所示,类BooksController中定义了方法fetchBooks(),并且该方法严重依赖于I/O操作。因为fetchBooks()从不同的供应商那里获取最近的书籍信息。