ruby + phantomjs 自动化测试 - GA

说起测试GA,真是一件枯燥乏味,重复性很高的工作,那么为什么我们不使用自动化测试代替它呢,显然,很多公司的产品迭代太快,ga也变化的比较频繁,但是确保ga工作正常,对于其他部门的工作是有很大帮助的,由于公司对于这块比较注重,而且曾经出现过ga被前端修复bug而影响,所以抽空倒腾了下如何对ga进行自动化测试,由于自身比较习惯使用ruby,所以本帖都是ruby的代码,思路是一样的,喜欢的童鞋可以用其他语言去实现。

首先说说开始考虑的实现方案:

1. 使用selenium+firefox的插件抓取request生成har文件,尝试过后发现不可行,点看此文章 http://www.cnblogs.com/timsheng/p/7209964.html

2. 使用proxy,讲浏览器请求server的request转发到本地,proxy的库有很多,ruby内置的webrick就很好用,但是尝试过后发现依然不行,webrick只能抓取http的request,我们网站是https协议的,抓取不到。

3. 使用evil-proxy, https://github.com/bbtfr/evil-proxy 这个库很强大,可以结合selenium使用,原理是运行时会生成自己的签名文件,然后将生成的签名文件import到浏览器就行了,具体如何操作请参考wiki,但是问题又来了,我们网站https的request都可以抓到,除了google的https request无法抓取,会提示无效签名。

4. ok,这些简单的方式都无法成功抓取ga的request,只能出绝招了,可能大家都知道,phantomjs是一个很强大的工具,它可以结合其他框架做headless网站测试,可以截图,不同于selenium截取当前页面图,它可以截取全屏截图,另外它可以做网页测试,最关键的是它可以进行网络监控。 传送门在此,http://phantomjs.org/

所以我们需要使用的是phantomjs, 去进行页面自动化,并且抓取生成的ga requests,用ruby去分析日志,并且进行校验pageview和event的事件是否触发,参数是否正确

不多说上代码:

首先看一下目录结构

我们先来看一下student_ga.js文件

/**
 * Wait until the test condition is true or a timeout occurs. Useful for waiting
 * on a server response or for a ui change (fadeIn, etc.) to occur.
 *
 * @param testFx javascript condition that evaluates to a boolean,
 * it can be passed in as a string (e.g.: "1 == 1" or "$(‘#bar‘).is(‘:visible‘)" or
 * as a callback function.
 * @param onReady what to do when testFx condition is fulfilled,
 * it can be passed in as a string (e.g.: "1 == 1" or "$(‘#bar‘).is(‘:visible‘)" or
 * as a callback function.
 * @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
 */

"use strict";

function waitFor(testFx, onReady, timeOutMillis) {
    var maxtimeOutMillis = timeOutMillis || 8000, //< Default Max Timout is 3s
    start = new Date().getTime(),
    condition = false,
    interval = setInterval(function() {
        if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
            // If not time-out yet and condition not yet fulfilled
            condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
        } else {
            if(!condition) {
                // If condition still not fulfilled (timeout but condition is ‘false‘)
                console.log("‘waitFor()‘ timeout");
                phantom.exit(1);
            } else {
                // Condition fulfilled (timeout and/or condition is ‘true‘)
                console.log("‘waitFor()‘ finished in " + (new Date().getTime() - start) + "ms.");
                typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it‘s supposed to do once the condition is fulfilled
                clearInterval(interval); //< Stop this interval
            }
        }
    }, 250); //< repeat check every 250ms
};

// initialise various variables
var page = require(‘webpage‘).create(),
    system = require(‘system‘),
    address;

page.viewportSize = {
    width: 1280,
    height: 800
};

// how long should we wait for the page to load before we exit
// in ms
var WAIT_TIME = 30000;

// if the page hasn‘t loaded after this long, something is probably wrong
// in ms
var MAX_EXECUTION_TIME = 30000;

// output error messages
var DEBUG = true

// a list of regular expressions of resources (urls) to log when we load them
var resources_to_log = [
    new RegExp(‘^http(s)?://(www|ssl)\.google-analytics\.com.*‘),
    new RegExp(‘^http(s)?://stats\.g\.doubleclick\.net.*‘)
];

// page.settings.resourceTimeout = 10000;

// check we have a url, if not exit
if (system.args.length === 1) {
    console.log(‘Usage: get_ga_resources.js http://www.yoururl.com‘);
    phantom.exit(1);
} else {
  // address is the url passed
  address = system.args[1];

  // create a function that is called every time a resource is requested
  // http://phantomjs.org/api/webpage/handler/on-resource-requested.html
  page.onResourceRequested = function (res) {
      // loop round all our regexs to see if this url matches any of them
      var length = resources_to_log.length;
      while(length--) {
          if (resources_to_log[length].test(res.url)){
              // we have a match, log it
              console.log(res.url);
          }
      }
  };

  // if debug is true, log errors, else ignore them
  page.onError = function(msg, trace){
      if (DEBUG) {
          console.log(‘ERROR: ‘ + msg);
          console.log(trace);
      }
  };

  // output console message
  // page.onConsoleMessage = function(msg) {
  //     console.log(msg);
  // };

  // page.onResourceTimeout = function(request) {
  //     console.log(request.errorCode);
  //     console.log(request.errorString);
  //     console.log(request.url);
  //     // console.log(‘Response (#‘ + request.id + ‘): ‘ + JSON.stringify(request));
  // };

  // page.onResourceError = function(resourceError) {
  //     console.log(‘Unable to load resource (#‘ + resourceError.id + ‘URL:‘ + resourceError.url + ‘)‘);
  //     console.log(‘Error code: ‘ + resourceError.errorCode + ‘. Description: ‘ + resourceError.errorString);
  // };

  // now all we have to do is open the page, wait WAIT_TIME ms and exit
    try {
        page.open(address, function (status) {
            console.log("Starting to open --" + address);
            if (status !== ‘success‘) {
                console.log("FAILED: to load " + system.args[1]);
                console.log(page.reason_url);
                console.log(page.reason);
                phantom.exit();
            } else {
              // page is loaded!
                if(address != page.url){
                    console.log(‘Redirected: ‘ + page.url)
                }
                // start to do actions on website
                console.log("Success to open --" + address);
                page.render("screenshot/homepage.png");

                // select top city london to click
                page.evaluate(function(s) {
                    console.log("Click top city -> London");
                    document.querySelector(".top-cities__city:nth-child(1)>a>img").click();
                    console.log("click it done!!!!");
                });

                // submit enquiry until srp load completely
                setTimeout(function(){
                    waitFor(function() {
                        // Check in the page if a specific element is now visible
                        return page.evaluate(function() {
                            console.log("determine if contact an expert element is visible? ")
                            cae_element = document.querySelector(".advicebar__btn.button.button--keppel.js-account-modal-enquire");
                            if (cae_element.offsetWidth > 0 && cae_element.offsetHeight > 0) {
                                return true;
                            } else {
                                return false;
                            };
                        });
                    }, function() {
                        console.log("Page_Url:" + page.url);
                        console.log("--- Get into search result page ---");
                        page.render("screenshot/search_result_page.png");
                        page.evaluate(function() {
                            console.log(document.querySelector(".advicebar__btn.button.button--keppel.js-account-modal-enquire").innerHTML);
                            document.querySelector(".advicebar__btn.button.button--keppel.js-account-modal-enquire").click();
                            console.log("Click contact an expert button");
                        });
                        console.log("--- Get into entry screen ---");
                        page.render("screenshot/entry_screen.png");

                        page.evaluate(function() {
                            document.querySelector("#js-account-modal-enquiry .account-modal__step--visible .button.button--secondary").click();
                            console.log("--- Get into sign up screen ---");
                            document.querySelector("#js-account-modal-enquiry input[name=‘full_name‘]").value = ‘tim sheng‘;
                            document.querySelector("#js-account-modal-enquiry input[name=‘telephone‘]").value = ‘123123123‘;
                            document.querySelector("#js-account-modal-enquiry input[name=‘email‘]").value = ("tim.sheng+" + (new Date().getTime()) + "@student.com");
                            document.querySelector("#js-account-modal-enquiry input[name=‘password‘]").value = ‘abc20052614‘;
                        });
                        page.render("screenshot/sign_up_screen.png");
                        page.evaluate(function() {
                            console.log(‘Click sign up button‘);
                            document.querySelector("#set-password-button").click();
                        });
                        waitFor(function() {
                            return page.evaluate(function() {
                                console.log("determine if confirm button is visible? on about you screen");
                                confirm_element = document.querySelector("#js-account-modal-enquiry #submit-about-you-button");
                                if (confirm_element.offsetWidth > 0 && confirm_element.offsetHeight > 0) {
                                    return true;
                                } else {
                                    return false;
                                };
                            });
                        }, function() {
                            console.log("--- Get into about you screen ---");
                            page.render("screenshot/about_you_screen.png");
                            page.evaluate(function() {
                                document.querySelector("#js-account-modal-enquiry #submit-about-you-button").click();
                            });
                            waitFor(function() {
                                return page.evaluate(function() {
                                    console.log("determine if budget field is visible? on about listing screen");
                                    budget_element = document.querySelector("#js-account-modal-enquiry input[name=‘budget‘]");
                                    if (budget_element.offsetWidth > 0 && budget_element.offsetHeight > 0) {
                                        return true;
                                    } else {
                                        return false;
                                    };
                                });
                            }, function() {
                                console.log("--- Get into about listing screen ---");
                                page.render("screenshot/about_listig_screen_unfilled.png");
                                page.evaluate(function() {
                                    // click date picker plugin
                                    document.querySelector("#js-account-modal-enquiry .date-picker").click();
                                    // select move in date
                                    document.querySelectorAll("#js-account-modal-enquiry .js-date-picker-move-in-fieldset input[class=‘js-date-picker-move-in-month‘]:not(:disabled)+label")[0].click();
                                    // select move out date
                                    document.querySelectorAll("#js-account-modal-enquiry .js-date-picker-move-out-fieldset input[class=‘js-date-picker-move-out-month‘]:not(:disabled)+label")[0].click();
                                    // input budget value
                                    document.querySelector("#js-account-modal-enquiry input[name=‘budget‘]").value = ‘1234‘;
                                    // input university value
                                    document.querySelector("#js-account-modal-enquiry .account-modal__step--visible input[name=‘university‘]").value = ‘london‘;
                                    // dispatch inputing event to elem
                                    var event = new Event(‘inputing‘);
                                    input_elem = document.querySelector("#js-account-modal-enquiry .account-modal__step--visible input[name=‘university‘]");
                                    input_elem.focus();
                                    input_elem.dispatchEvent(event);
                                });
                                waitFor(function() {
                                    return page.evaluate(function() {
                                        console.log("determine if university is visible? on autocomplete list");
                                        uni_element = document.querySelector(‘#js-account-modal-enquiry .autocomplete__item:first-child .autocomplete__item__link‘);
                                        if (uni_element.offsetWidth > 0 && uni_element.offsetHeight > 0) {
                                            return true;
                                        } else {
                                            return false;
                                        };
                                    });
                                }, function() {
                                    console.log("--- University is visible on autocomplete list");
                                    page.render("screenshot/about_listing_university.png");
                                    page.evaluate(function() {
                                        document.querySelector(‘#js-account-modal-enquiry .autocomplete__item:first-child .autocomplete__item__link‘).click();
                                    });
                                    page.render("screenshot/about_listing_screen_filled.png");
                                    page.evaluate(function() {
                                        console.log("Click submit enquiry button");
                                        document.querySelector("#js-account-modal-enquiry .account-modal__step--visible #submit-about-stay-button").click();
                                    });
                                    waitFor(function() {
                                        return page.evaluate(function() {
                                            console.log("determine if success button is visible? on leads process screen");
                                            success_element = document.querySelector("#js-account-modal-enquiry .account-modal__step--visible .button.button--primary");
                                            if (success_element.offsetWidth > 0 && success_element.offsetHeight > 0) {
                                                return true;
                                            } else {
                                                return false;
                                            };
                                        });
                                    }, function() {
                                        console.log("submit enquiry from srp cae successfully!");
                                        page.render("screenshot/enquiry_success_screen.png");
                                    });
                                });
                            });
                        });
                    });
                },5000);

                setTimeout(function () {
                  phantom.exit();
                }, WAIT_TIME);
            }
        });
    } finally {
        // if we are still running after MAX_EXECUTION_TIME ms exit
        setTimeout(function() {
            console.log("FAILED: Max execution time " + Math.round(MAX_EXECUTION_TIME) + " seconds exceeded");
            phantom.exit(1);
        }, MAX_EXECUTION_TIME);
    }
}

  

然后写个ruby类去解析这个log, cop.rb

require ‘uri‘

module Cop
  class Logger
    attr_accessor :ga_requests

    def initialize path
      @ga_requests = open_log_file path
    end

    # fetch pageview ga
    def pageview
      Gas.new ga_requests, ‘pageview‘
    end

    # fetch event ga
    def event
      Gas.new ga_requests, ‘event‘
    end

    # get all google analytics request records
    def open_log_file path
      all_ga_requests = []
      File.open("#{path}").each do |line|
          all_ga_requests << line if line.include? ‘google‘
      end
      all_ga_requests
    end
  end

  # Gas is a class which is consisted of a list of specific ga requests
  class Gas
    attr_accessor :gas, :type

    VALID_KEYS = [‘dl‘,‘dp‘,‘ul‘,‘dt‘,‘ec‘,‘ea‘,‘el‘,‘cd17‘,‘cd15‘,‘cd5‘,‘cd1‘,‘cd14‘,‘cg1‘,‘cg2‘,‘cd18‘,‘cd2‘]

    def initialize all_gas, type
      h_gas = handle_gas all_gas, type
      @gas = get_expected_gas h_gas
      @type = type
    end

    # return the count of gas
    def count
      gas.count
    end

    # use the value of key to get corresponding pageview record
    # it is better for pageview ga using dp to get value
    # use the value of key to get corresponding event record
    # it is better for event ga using el to get value
    def get_gas_by value
      gas.each do |ga|
        ga.each do |k,v|
          if v == value
            return ga
          end
        end
      end
    end

    private

    # fetch ga requests by type
    def handle_gas all_gas, type
      new_gas_arr = []
      all_gas.each do |all_ga|
        if all_ga.include? type
          decoded_all_ga = URI.decode(all_ga)
          new_gas_arr << qs_to_hash(decoded_all_ga)
        end
      end
      new_gas_arr
    end

    # get expected gas
    def get_expected_gas gas
      expected_gas = []
      gas.each do |ga|
        expected_ga = {}
        ga.each do |k,v|
          if VALID_KEYS.include? k
            expected_ga[k] = v
          else
            next
          end
        end
        expected_gas << expected_ga
      end
      expected_gas
    end

    # decode url
    def qs_to_hash query
      keyvals = query.split(‘&‘).inject({}) do |result, q|
        k,v = q.split(‘=‘)
        if !v.nil?
           result.merge({k => v})
        elsif !result.key?(k)
          result.merge({k => true})
        else
          result
        end
      end
      keyvals
    end
  end
end

Gas类返回的是hash,我希望取hash的value根据object.xx  的形式,而不是hash[] 的方式,所以重新打开hash类,根据ga的常用参数使用define_method动态定义一些方法

hash.rb

class Hash
  VALID_KEYS = [‘dl‘,‘dp‘,‘ul‘,‘dt‘,‘ec‘,‘ea‘,‘el‘,‘cd17‘,‘cd15‘,‘cd5‘,‘cd1‘,‘cd14‘,‘cg1‘,‘cg2‘,‘cd18‘,‘cd2‘]

  def self.ga name
    define_method "#{name}" do
      self["#{name}"]
    end
  end

  VALID_KEYS.each do |e|
    ga "#{e}"
  end

end

基本准备工作差不多了,现在我们用rspec去管理测试用例,在执行case前,我们需要去清洗一下环境,删除log文件,截图,然后执行phantomjs脚本,

bridge.rb

module Cop

  def clear_env
    `rm -rf screenshot/*.png`
    `rm -rf log/*.log`
  end

  def submit_lead_from_srp_cae
    `phantomjs js/student_ga.js https://hurricane-cn.dandythrust.com > log/ga.log`
  end
end

让我们在根目录下rspec --init一下,生成spec_helper.rb 文件,在此文件中,引入cop.rb, hash.rb, bridge.rb以便于在_spec文件中使用

spec_helper.rb

require ‘cop‘
require ‘hash‘
require ‘bridge‘
include Cop

新建个ga_spec.rb文件,开始编写case

require "spec_helper"

describe "GA Checking" do
  describe "New user submit lead from srp cae" do

    before(:all) do
      clear_env
      submit_lead_from_srp_cae
    end

    let(:logger) { logger= Cop::Logger.new "log/ga.log" }

    context "Pageview" do
      let(:pageview_gas) { logger.pageview }

      it "should be correct on homepage" do
        result = pageview_gas.get_gas_by "/"
        expect(result.dp).to eql "/"
        expect(result.ul).to eql "en-us"
        expect(result.cd17).to eql "3rd Party Login" unless result.cd17.nil?
        expect(result.cd15).to eql "zh-cn"
        expect(result.cd5).to eql "home"
        expect(result.cd1).to eql "desktop"
        expect(result.cd14).to eql "Special Offers"
        expect(result.cg1).to eql "Home Page"
      end

      it "should be correct on search result page" do
        result = pageview_gas.get_gas_by "/uk/london"
        expect(result.dp).to eql "/uk/london"
        expect(result.ul).to eql "en-us"
        expect(result.cd17).to eql "3rd Party Login" unless result.cd17.nil?
        expect(result.cd18).to eql "231004024"
        expect(result.cd15).to eql "zh-cn"
        expect(result.cd5).to eql "search"
        expect(result.cd2).to eql "London"
        expect(result.cd1).to eql "desktop"
        expect(result.cg1).to eql "Search"
        expect(result.cg2).to eql "City"
      end

      it "should be correct on entry screen" do
        result = pageview_gas.get_gas_by "/modal/enquiry/cae_srp/signup"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup"
        expect(result.ul).to eql "en-us"
      end

      it "should be correct on sign up screen" do
        result = pageview_gas.get_gas_by "/modal/enquiry/cae_srp/signup/email"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email"
        expect(result.ul).to eql "en-us"
      end

      it "should be correct on about you screen" do
        result = pageview_gas.get_gas_by "/modal/enquiry/cae_srp/signup/email/confirm_contact_info"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/confirm_contact_info"
        expect(result.ul).to eql "en-us"
      end

      it "should be correct on about stay screen" do
        result = pageview_gas.get_gas_by "/modal/enquiry/cae_srp/signup/email/about_stay"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/about_stay"
        expect(result.ul).to eql "en-us"
      end

      it "should be correct on enquiry success screen" do
        result = pageview_gas.get_gas_by "/modal/enquiry/cae_srp/signup/email/enq_submitted"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/enq_submitted"
        expect(result.ul).to eql "en-us"
      end
    end

    context "Event" do
      let(:event_gas) { logger.event }

      it "click top city on homepage is correct" do
        result = event_gas.get_gas_by "topCities"
        expect(result.dp).to eql "/"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "topCities"
        expect(result.ec).to eql "homePage"
        expect(result.el).to eql "city:231004024"
        expect(result.cd17).to eql "3rd Party Login"
        expect(result.cd15).to eql "zh-cn"
        expect(result.cd5).to eql "home"
        expect(result.cd1).to eql "desktop"
        expect(result.cd14).to eql "Special Offers"
        expect(result.cg1).to eql "Home Page"
      end

      it "click contact an expert on srp is correct" do
        result = event_gas.get_gas_by "cae > button:getInTouch"
        expect(result.dp).to eql "/uk/london"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "cae > button:getInTouch"
        expect(result.ec).to eql "searchClick"
        expect(result.el).to eql "231004024-London"
        expect(result.cd17).to eql "3rd Party Login"
        expect(result.cd15).to eql "zh-cn"
        expect(result.cd5).to eql "search"
        expect(result.cd2).to eql "London"
        expect(result.cd1).to eql "desktop"
        expect(result.cg1).to eql "Search"
        expect(result.cg2).to eql "City"
      end

      it "click sign up with email on entry screen is correct" do
        result = event_gas.get_gas_by "continueWithEmail"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "signupScreen"
        expect(result.ec).to eql "enquiryFlow"
        expect(result.el).to eql "continueWithEmail"
      end

      it "click continue button on sign up screen is correct" do
        result = event_gas.get_gas_by "continueBtnClicked"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "signupWithEmailScreen"
        expect(result.ec).to eql "enquiryFlow"
        expect(result.el).to eql "continueBtnClicked"
      end

      it "click request details button on about you screen is correct" do
        result = event_gas.get_gas_by "requestDetailsBtnClicked"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/confirm_contact_info"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "confirmContactInfo:email"
        expect(result.ec).to eql "enquiryFlow"
        expect(result.el).to eql "requestDetailsBtnClicked"
      end

      it "focus destination uni on about stay screen is correct" do
        result = event_gas.get_gas_by "focus:destinationUniversity"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/about_stay"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "aboutStay"
        expect(result.ec).to eql "enquiryFlow"
        expect(result.el).to eql "focus:destinationUniversity"
      end

      it "click submit form button on about stay screen is correct" do
        result = event_gas.get_gas_by "submitBtnClicked"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/about_stay"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "aboutStay"
        expect(result.ec).to eql "enquiryFlow"
        expect(result.el).to eql "submitBtnClicked"
      end

      it "enquiry submitted is correct" do
        result = event_gas.get_gas_by "cae_srp"
        expect(result.dp).to eql "/modal/enquiry/cae_srp/signup/email/enq_submitted"
        expect(result.ul).to eql "en-us"
        expect(result.ea).to eql "success"
        expect(result.ec).to eql "enquiry"
        expect(result.el).to eql "cae_srp"
      end
    end
  end

end

The End

时间: 2024-10-11 01:56:54

ruby + phantomjs 自动化测试 - GA的相关文章

python selenium+phantomJS自动化测试环境

0x00配置phantomJS 1. 在windows平台下 此种方法是弹浏览器进行自动化测试的. 1.下载谷歌的驱动 https://chromedriver.storage.googleapis.com/index.html 2.将解压后的chromedriver.exe放到chrome浏览器的安装目录下. 3.在代码中调用浏览器驱动,执行自动化操作. chromedriver = 'chromedriver绝对路径' driver = webdriver.Chrome(chromedriv

使用Jenkins+Calabash+Cocoapods搭建iOS持续集成环境

持续集成 持续集成究竟是什么呢?根据敏捷大师Martin Fowler的定义: 持续集成是一种软件开发实践.在持续集成中,团队成员频繁集成他们的工作成果,一般每人每天至少集成一次,也可以多次.每次集成会经过自动构建(包括自动测试)的检验,以尽快发现集成错误.许多团队发现这种方法可以显著减少集成引起的问题,并可以加快团队合作软件开发的速度. 只要是开发就有分工,哪怕是自己一个写也要分成多个模块.随着项目越来越大,模块也越来越多,各个模块是否可以征程协作就成了问题,有了持续集成,可以有如下好处: 持

前后端分离后的前端时代

本文从前端开发的视角,聊一聊前后端分离之后的前端开发的那些事儿.阅读全文,大约需要8分钟. 什么是前后端分离 除了前端之外都属于后端了. 你负责貌美如花,我负责赚钱养家 在传统的像ASP,JSP和PHP等开发模式中,前端是处在一个混沌的状态中,可以说是没有独立的"人格"可言. 前端负责切图和编写静态页面模板,后端将数据渲染到前端提供的页面模板中,最后将页面渲染到浏览器展示. 这个过程中,前端只提供页面模板或者写一些JavaScript脚本,有的甚至JS脚本都是后端来写,前端的作用只局限

Ruby实现Http自动化测试(一)----------类宏

最近在做一个restful API的项目,项目测试主要是发送HTTP请求(GET,POST,DELETE,PUT等),并检查返回结果. 以往我们测试都是先写测试用例,通常是一个EXECEL表格.这里面会写好每个测试例的输入,测试步骤和期望结果.然后再根据每个测试例的通过情况,更新另一个EXECEL中对应测试例的测试结果(通过or失败,还有一些备注信息等.) 测试人员需要写好测试例,并用一个HTTP工具对每个测试例进行测试,并人工检查返回结果,决定测试例的成功与失败.这样的结果就是,每次代码发布后

从0到1,教你实现基于Ruby的watir-webdriver自动化测试

一.为什么选择Ruby [1]完全开源. [2]多平台:Ruby可以运行在Linux, UNIX, Windows, MS-DOS, BeOS, OS/2.. [3]多线程:线程就是指在一个程序中处理若干控制流的功能.与OS提供的进程不同的是,线程可以共享内存空间. [4]完全面向对象. [5]不需要内存管理:具有垃圾回收(Garbage Collect, GC)功能,能自动回收不再使用的对象. [6]解释执行:其程序无需编译即可轻松执行. [7]功能强大的字符串操作/正则表达式. [8]具有异

Nightmare基于phantomjs的自动化测试套件

今天将介绍一款自动化测试套件名叫nightmare,他是一个基于phantomjs的测试框架,一个基于phantomjs之上为测试应用封装的一套high level API.其API以goto, refresh, click, type…等简单的常用e2e测试动作封装,使得其语义清晰,简洁.其官方在http://www.nightmarejs.org/. 如果你的项目测试不需要想需求和测试人员理解,那么基于nightmare测试或许是一个好的选择,你的降低测试代码的成本,以及测试套件的部署.我们

基于Ruby的Watir-WebDriver自动化测试框架

Watir-WebDriver       —— 软件测试的自动化时代 QQ群:160409929 支持哪些浏览器? 几乎所有的浏览器: 比如Firefox, Chrome 和IE,除了Safari. 支持网页上哪些元素? watir-webdriver支持所有的HTML元素 运行模式是什么? Watir-WebDriver是基于ruby开发web驱动框架 自动化测试框架 根据不同业务开发相应自动化用例,由Ruby测试框架统一调用分析展示.实现出入口统一,工具类封装:降低用例开发复杂度,框架统一

Windows环境搭建Web自动化测试框架Watir(基于Ruby) 第1章

一.前言     Web自动化测试一直是一个比较迫切的问题,对于现在web开发的敏捷开发,却没有相对应的敏捷测试,故开此主题,一边研究,一边将Web自动化测试应用于工作中,进而形成能够独立成章的博文,希望能够为国内web自动化测试的发展做一点绵薄的贡献吧,笑~ 二.Watir搭建流程 图1-1 需要安装的工具     下载地址:http://railsinstaller.org/     因为安装Ruby还需要用到其他的一些开发工具集,所以建议从网站http://railsinstaller.o

基于Ruby的watir-webdriver自动化测试方案与实施(三)

接着基于Ruby的watir-webdriver自动化测试方案与实施(二) http://www.cnblogs.com/Javame/p/4159468.html 继续 ... ... 编写脚本首先要学会捕获元素,接下来就要学习页面元素的捕获. 页面元素 attribute_value 获取当前控件的属性 Value = ie.link(:id=>'xxx’).attribute_value("href") rand_select 随机选择select list中的某一项 ie