主题和主题组件的端到端系统测试

为主题编写自动化测试是主题开发过程中的一个重要部分,它可以帮助确保主题引入的功能随着时间推移与 Discourse 核心功能能够良好地协同工作。

目前,Discourse 支持两种编写主题回归测试的方式。第一种主要遵循 EmberJS 的方式,只涉及测试客户端代码。第二种方式是编写 Rails 系统测试,它允许您同时测试服务器端代码和客户端代码。本文档将重点介绍为主题编写 Rails 系统测试,这也是我们建议主题作者在为其主题编写测试时关注的重点。

主题的 Rails 系统测试

在底层,Discourse 使用 RSpecCapybara 测试框架来运行 Rails 系统测试。要开始使用,需要具备 RSpec 和 Capybara 的基本知识,我们建议您在开始之前先阅读以下链接:

编写主题系统测试的指南和技巧

以下是在编写系统测试时应遵循的一些指南:

  • 系统测试应位于主题目录下的 spec/system 目录中。

  • spec/system 目录下的每个文件应遵循 \u003c系统测试的描述\u003e_spec.rb 格式。

  • 顶层的 RSpec describe 块需要包含 system: true 元数据。示例:

    RSpec.describe "Testing A Theme or Theme Component", system: true do
      it "displays the component" do
        ...
      end
    end
    
  • upload_themeupload_theme_component 辅助方法可用,并且需要在运行测试前调用。示例:

    RSpec.describe "Testing A Theme or Theme Component", system: true do
      let!(:theme) do
        upload_theme
      end
    
      # 如果您的主题是一个组件,则使用 `upload_theme_component`
      #
      # let!(:theme_component) do
      #   upload_theme_component
      # end
    
      it "displays the component" do
        ...
      end
    end
    
  • 可以通过在 theme 对象上调用 update_setting 方法并保存主题来在系统测试中更改主题的设置。

    示例:

    RSpec.describe "Testing A Theme", system: true do
      let!(:theme) do
        upload_theme
      end
    
      it "does not display the theme when `should_render` theme setting is false" do
        theme.update_setting(:should_render, false)
        theme.save!
    
        expect(page).not_to have_css("#some-identifier")
      end
    end
    
  • Discourse 使用 fabrication gem,它允许我们轻松地为每个测试设置所需的测试数据。Discourse 核心中可用的 fabricator 完整列表 也可在主题的系统测试中使用。

    示例:

    RSpec.describe "Testing A Theme", system: true do
      let!(:theme) do
        upload_theme
      end
    
      it "displays the theme" do
        user = Fabricate(:user)
        category = Fabricate(:category)
        topic = Fabricate(:topic)
        topic_2 = Fabricate(:topic, title: "This is topic number 2")
    
        ...
      end
    end
    
  • 使用 sign_in 辅助方法来针对不同的用户配置文件进行测试。

    示例:

    RSpec.describe "Testing A Theme", system: true do
      let!(:theme) do
        upload_theme
      end
    
      it "does not display the theme for a regular user" do
        user = Fabricate(:user)
        sign_in(user)
    
        ...
      end
    
      it "displays the theme for a staff user" do
        admin = Fabricate(:admin)
        sign_in(admin)
    
        ...
      end
    end
    
  • 有时您会希望使查询和检查页面部分对系统测试来说更简单、更易于重用。为此,您可以使用 PageObjects 的概念,这在 核心代码 中经常可以看到。

    示例:

    # frozen_string_literal: true
    
    module PageObjects
      module Components
        class MyCustomComponent < PageObjects::Components::Base
          COMPONENT_SELECTOR = ".my-custom-component"
    
          def click_action_button
            find("#{COMPONENT_SELECTOR} .action-button").click
          end
    
          def has_content?(content)
            has_css?("#{COMPONENT_SELECTOR} .content", text: content)
          end
        end
      end
    end
    

    然后,您可以通过在系统测试文件的顶部使用 Ruby 内置的 require_relative 来导入它。

    require_relative "page_objects/components/my_custom_component"
    

运行主题系统测试

可以使用 discourse_theme CLI rubygem 运行主题系统测试,可以通过这些说明进行安装。

安装 discourse_theme CLI 后,您可以通过运行以下命令来运行主题目录中的所有系统测试:

discourse_theme rspec .

在首次运行新主题的 rspec 命令时,系统会提示您是想使用本地 Discourse 开发环境还是使用Docker 容器来运行系统测试,后者将为您配置好开发环境。除非您是经验丰富的 Discourse 插件或主题开发者,否则我们建议选择 n 并使用 Docker 容器运行测试,因为这样可以开箱即用。

discourse_theme rspec 命令还支持运行单个 spec 目录、文件和带行号的文件。

discourse_theme rspec /path/to/theme/spec/system
discourse_theme rspec /path/to/theme/spec/system/my_system_spec.rb
discourse_theme rspec /path/to/theme/spec/system/my_system_spec.rb:12

有头模式

默认情况下,主题系统测试使用 Google Chrome 的无头模式运行。这是一种浏览器不渲染任何屏幕内容的模式,可以使测试运行更快完成。然而,使用有头模式的 Google Chrome 查看您编写的系统测试正在执行的操作通常很有用。您可以通过向 discourse_theme rspec 命令传递 --headful 选项来启用此模式。

discourse_theme rspec . --headful

上述命令将以有头模式运行系统测试,可以直观地看到测试的运行情况。

您还可以使用 pause_test 辅助方法暂停测试执行,以便检查应用程序在浏览器中的当前状态。

示例:

RSpec.describe "Testing A Theme", system: true do
  let!(:theme) do
    upload_theme
  end

  it "displays the theme" do
    visit("/")
    click("#some-button")
    pause_test
    # ...
  end
end

此文档是版本控制的 - 请在 github 上建议更改。

18 个赞

我注意到在组件的测试中,通常使用 let!(:theme) 而不是 let!(:theme_component)。例如,在此测试中:

然而,指南建议为主题组件使用 let!(:theme_component)

是否有理由像本指南中所述那样使用 theme_component

2 个赞