+7

Xây dựng chức năng mô phỏng lại hành động người dùng bằng công cụ kiểm thử tự động Selenium

Như các bạn đã biết, Selenium là một trong những công cụ kiểm thử phần mềm tự động mã nguồn mở (open source test automation tool) mạnh mẽ nhất hiện nay cho việc kiểm thử ứng dụng Web. Selenium sẻ kiểm thử web thông qua các kịch bản (là danh sách các bước để thực hiện một chức năng nào đó) cho trước. Selenium script có thể chạy được trên hầu hết các trình duyệt như IE, Mozilla FireFox, Chrome, Safari, Opera; và hầu hết các hệ điều hành như Windows, Mac, Linux.

Ngoài chức năng kiểm thử chúng ta hoàn toàn có thể "chế tác" lại nó để xây dựng lên các chức năng đòi hỏi mô phỏng lại các hành động người dùng. Trong RoR có một vài gem cung cấp cho ta thư viện để làm việc với selenimum bằng chính ngôn ngủ ruby(selenium thuần là javascript), ở bài viết lần này mình sử dụng gem "selenium-webdriver" để xây dựng nên 1 chức năng như mô tả sau: Hằng ngày lúc 7h sáng truy cập vào website A có địa chỉ là http://www.ServerA.com sau đó click vào button login để chuyển sang trang login và đăng nhập với id và password lần lượt là acount_a và Aa@123. Nếu đăng nhập thất bại thì gửi thông báo lỗi qua email admin@admin.com. Nếu đăng nhập thành công thì chuyển sang địa chỉ http://www.ServerA.com/export_csv rồi download file về lưu vào thư mục download/<ngày download file> trên server hiện tại của mình của mình.

Tại trang ServerA.com có button chuyển sang trang đăng nhập có id là: "login_now" tại trang login có 2 field để điền id, password và 1 button submit có id lần lượt là "staff_id", "staff_password" và "login_button". Nếu đăng nhập không thành công sẻ xuất hiện các message error có class là "mess_error".

Tại trang http://www.ServerA.com/export_csv có button export csv có id là "export_csv_now".

Nêu sau 5phut mà file vẫn chưa được download hoặc download chưa xong thì xóa thư mục được tạo ra từ đầu để chứa file download.

Đóng driver khi thực hiện các công việc trên xong.

Cài đặt

#/Gemfile
gem "selenium-webdriver", "~> 3.5.2" 

Sau đó chạy bundle install để cài đặt gem đó vào project. Và để nó hoạt đồng chúng ta phải sử dụng các browser WebDriver. Cụ thể ở đây mình sẻ dùng ChromeDriver. Các bạn có thể tải về bản mới nhất theo từng hệ điều hành tại đây.

Ngoài ra nếu bạn muốn dùng chế độ Headless thì có thể cài thêm gem "headless"(search google headless browser nếu bạn chưa hiểu về headless nhé).

Thực hiện

Có rất nhiều option thiết lập các bạn có thể tham khảo tại dây.

1.

Đầu tiên mình tạo một Service có tên là AutoDownload để chứa phương thức thực thi công việc download file từ server A như sau:

#/app/services/auto_download_service.rb
Class AutoDownloadService
    def self.download_server_a
    end
end

2.

Tạo thư mục để lưu file download(có url là /download/<ngày download file>)

#/app/services/auto_download_service.rb
Class AutoDownloadService
    def self.download_server_a
         location = "#{File.expand_path(Rails.root.to_s)}/download/#{Time.now.strftime '%d%m%Y'}"
    end
end

3.

Tiếp theo ta tạo 1 driver cho phép download trên browser mà không cần phải hỏi lại trước khi save đồng thời thiết lập thư mục lưu file chính là thư mục mà ta vừa tạo ở bước 2.

#/app/services/auto_download_service.rb
Class AutoDownloadService
    def self.download_server_a
        location = "#{File.expand_path(Rails.root.to_s)}/download/#{Time.now.strftime '%d%m%Y'}"
        prefs = {prompt_for_download: false, default_directory: location}
        options = Selenium::WebDriver::Chromium::Options.new
        options.add_preference :download, prefs
        options.add_argument "--ldisable-gpu --no-sandbox"
        @driver = Selenium::WebDriver.for :chromium, options: options, profile: profile
    end
end

Khi chạy đến đây nếu ko dùng headless thì chúng ta sẽ thấy trình duyệt chromedriver được mở và khi download mọi thứ trên trình duyệt này đều được auto save vào thư mục có location như ở trên.

4.

Tiếp theo chúng ta sẻ thực hiện công việc truy cập và đăng nhập vào server A như yêu cầu.

Thứ tự công việc la cần làm như sau

#/app/services/auto_download_service.rb
Class AutoDownloadService
    def self.download_server_a
        location = "#{File.expand_path(Rails.root.to_s)}/download/#{Time.now.strftime '%d%m%Y'}"
        prefs = {prompt_for_download: false, default_directory: location}
        options = Selenium::WebDriver::Chromium::Options.new
        options.add_preference :download, prefs
        options.add_argument "--ldisable-gpu --no-sandbox"
        @driver = Selenium::WebDriver.for :chromium, options: options, profile: profile
        @driver.navigate.to "http://www.ServerA.com"
        @driver.find_element(id: "login_now").submit
        @driver.find_element(id: "staff_id").send_key "acount_a"
        @driver.find_element(id: "staff_password").send_key "Aa@123"
        @driver.find_element(id: "login_button").submit
        if @driver.find_elements(class: "mess_error").size.zero?
            #Tiếp tục chuyển đến trang export csv là download file
        else
            #Thực hiện gửi mail thông báo đăng nhập thất bại như yêu cầu như yêu cầu
        end
    end
end

Việc gửi mail thì khá đơn giản và các bạn có thể tham khảo cách thức để làm việc với mailler ở nhiều bài viết khác trên viblo. Mình xin bỏ qua phần này và tiếp lục với phần download file.

5.

Tiếp theo chúng ta di chuyển đến trang http://www.ServerA.com/export_csv thực hiện công việc download và kiểm tra file sau 5 phút như yêu cầu.

#/app/services/auto_download_service.rb
Class AudoDownloadService
    def self.download_server_a
        location = "#{File.expand_path(Rails.root.to_s)}/download/#{Time.now.strftime '%d%m%Y'}"
        prefs = {prompt_for_download: false, default_directory: location}
        options = Selenium::WebDriver::Chromium::Options.new
        options.add_preference :download, prefs
        options.add_argument "--ldisable-gpu --no-sandbox"
        driver = Selenium::WebDriver.for :chromium, options: options, profile: profile
        driver.navigate.to "http://www.ServerA.com"
        driver.find_element(id: "login_now").submit
        driver.find_element(id: "staff_id").send_key "acount_a"
        driver.find_element(id: "staff_password").send_key "Aa@123"
        driver.find_element(id: "login_button").submit
        if driver.find_elements(class: "mess_error").size.zero?
            driver.navigate.to "http://www.ServerA.com/export_csv"
            driver.find_element(id: "export_csv_now").submit
            sleep 300
            path = "#{location}/*.csv"
            file = Dir.glob(path)
            if file.size.zero?
                FileUtils.rm_rf location
            end
            driver.quit
        else
            #Thực hiện gửi mail thông báo đăng nhập thất bại như yêu cầu như yêu cầu
        end
    end
end

6.

Cuối cùng chỉ cần set cho việc download được thực thi hằng ngày vào lúc 7 giờ sáng trong schedule nữa là xong.

#/config/schedule.rb
every :day, at: "07:00" do
  runner "AutoDownloadService.download_server_a"
end

Kết luận

Hi vọng những chia sẻ trên sẽ ít nhiều giúp ích cho bạn trong một số trường hợp khi cần làm việc trên 1 webserver khác mà nó không cung cấp API. Bài viết không tránh khỏi các sai sót mong nhận được sự góp ý của tất cả mọi người.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí