admin管理员组

文章数量:1663670

1. 前言

        前面系列文章中详细介绍了 Geb 页面自动化框架。本文旨在基于前面的内容,来实战演示 Geb 的使用,包括元素的定位,页面的建模等。

 

2. 任务

        本系列以 QQ 邮箱的操作为背景,会覆盖邮箱登陆,邮件读取,写邮件等常用场景。本篇主要来谈 QQ 邮箱的登陆操作。

 

2.1 建立项目

        首先,我们需要建立一个 Maven 项目来承载我们的代码。笔者这里直接给出使用 Geb 进行 UI 自动化时,需要的 Maven pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache/POM/4.0.0"
         xmlns:xsi="http://www.w3/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache/POM/4.0.0 http://maven.apache/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.qq.ui</groupId>
    <artifactId>demo</artifactId>
    <version>1.0-SNAPSHOT</version>

    <properties>
        <java.version>1.8</java.version>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.codehaus.groovy</groupId>
            <artifactId>groovy-all</artifactId>
            <version>2.5.2</version>
        </dependency>
        <dependency>
            <groupId>org.gebish</groupId>
            <artifactId>geb-spock</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>org.seleniumhq.selenium</groupId>
            <artifactId>selenium-server</artifactId>
            <version>3.6.0</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
        </dependency>      
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.6.0</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-core</artifactId>
            <version>1.0.13</version>
        </dependency>
        <dependency>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
            <version>1.0.13</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                    <compilerId>groovy-eclipse-compiler</compilerId>                   
                </configuration>
                <dependencies>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-compiler</artifactId>
                        <version>3.0.0-01</version>
                    </dependency>
                    <dependency>
                        <groupId>org.codehaus.groovy</groupId>
                        <artifactId>groovy-eclipse-batch</artifactId>
                        <version>2.5.2-01</version>
                    </dependency>             
                </dependencies>
            </plugin>

            <plugin>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>2.20.1</version>
                <configuration>
                    <useFile>false</useFile>
                    <includes>
                        <include>**/*Spec.java</include>
                        <include>**/*Test.java</include>
                    </includes>
                    <argLine>-Dfile.encoding=UTF-8</argLine>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

整个项目的概览如下,文章末尾会给出整个项目的 git 地址:

moudlespages 包里分别存放建模的模块和页面,util 包里面提供了创建 Browser 对象的方法,qq 包里面收拢了 qq 邮箱提供给用户的操作的各种方法。

 

2.2 页面建模

        下面是登陆 QQ 邮箱页面,从该页面我们可以获得登陆邮箱的 URL: https://mail.qq/cgi-bin/loginpage 和登陆表单的位置,登陆页面的标题,这让我们得四个信息:

  • QQ 邮箱的基本 URL 是:https://mail.qq/
  • 登陆页面的路径是:cgi-bin/loginpage
  • QQ 的登陆表单是嵌入在一个 iframe 里面的
  • 登陆页面的标题是:登录QQ邮箱

QQ 邮箱的基本路径将是我们创建操作 QQ 邮箱的浏览器对象 Browser 的 baseUrl,登陆页面的路径将是建模后的登陆页面的 url 属性。实际的登陆操作应该在表单控件所在的 iframe 的上下文执行。可以使用登陆页面的 title 属性来判断浏览器当前是否在登陆页面。

 

在登陆页面上用户关心的内容有三块:账户输入框,密码输入框,登陆按钮。根据前面的分析,我们知道这些页面内容都是在一个单独的 iframe 里面的,所以这些内容都应该体现在建模后的 iframe 页面中。而登陆页面本身包含的内容就只是这个 iframe 元素,下面给出了建模后的登陆页面和 iframe 页面:

登陆页面:LoginPage.groovy

package pages

import geb.Page

/**
 * @author leiting.hlt
 * @date 2018/12/12
 */
class LoginPage extends Page {

    static url = 'cgi-bin/loginpage'
    static at = { title.contains('登录QQ邮箱') }

    static content = {
        loginFrame(page: LoginIFrame) { $('iframe#login_frame') }
    }

    def login(String username, String password) {
        withFrame(loginFrame) {
            // now at, LoginIFrame page
            innerLogin(username, password)
        }
    }
}

LoginPage 页面中向用户暴露了 login() 方法,隐藏了页面的实现细节,用户不需要关心页面表单,也不需要直接与这些页面元素交互,只要提供用户名和密码就行了。在 login() 方法内部,实际上使用了 withFrame 方法在页面内容 loginFrame 所表示的 iframe 的上下文内执行操作,而该 iframe 本身也只是暴露了一个简单的方法给外部调用。整个页面逻辑非常清晰。我们也看到 LoginPage 页面的 at 检查器中使用了页面标题作为检查依据,只有页面标题包含给定字符串时,at 检查器才会执行成功,浏览器才会确认自己当前的确是在 LoginPage 页面。

 

实际表单控件所在的 iframe: LoginIFrame.groovy

package pages

import geb.Page
import geb.module.TextInput

/**
 * @author leiting.hlt
 * @date 2018/12/12
 */
class LoginIFrame extends Page {

    static content = {
        nameInput { $('input', name: 'u') }
        passwordInput { $('input', type: 'password') }
        submit(to: MailIndexPage, toWait: true) { $('input#login_button') }
    }

    def innerLogin(String username, String password) {
        nameInput.module(TextInput).text = username
        passwordInput = password
        submit.click()
    }
}

LoginIFrame 页面定义了用户实操的三个页面内容:账户输入框,密码输入框,登陆按钮。值得注意的是 submit 的定义中,通过 to 选项指定了 submit 被点击后浏览器应该处于哪个页面,此处即为邮箱的首页,Geb 会检查浏览器最终是否在 to 所指定的页面。

 

 

本文标签: 实战邮箱GEBUIqq