Slide 1

Slide 1 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run BUILDING THE NEW RAILS System Tests

Slide 2

Slide 2 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run Hi! I’m Eileen M. Uchitelle

Slide 3

Slide 3 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run I’m a Systems Engineer @

Slide 4

Slide 4 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run I’m on the Core Team

Slide 5

Slide 5 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run You can find me online @eileencodes

Slide 6

Slide 6 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run BUILDING THE NEW RAILS System Tests

Slide 7

Slide 7 text

At the 2014 RailsConf…

Slide 8

Slide 8 text

No content

Slide 9

Slide 9 text

IS DEAD

Slide 10

Slide 10 text

Today we do [Rails does] nothing to encourage full system tests. There's no default answer in the stack. That's a mistake we’re going to fix. “ —DHH in “TDD is dead. Long live testing.” http://david.heinemeierhansson.com/2014/tdd-is-dead-long-live-testing.html

Slide 11

Slide 11 text

3 years later…

Slide 12

Slide 12 text

Zomg, Rails 5.1 has system testing!!1!11!

Slide 13

Slide 13 text

Wait, what’s a system test?

Slide 14

Slide 14 text

Tests your application as a whole system

Slide 15

Slide 15 text

gem 'capybara', '~> 2.13.0' gem 'selenium-webdriver' Rails 5.1 Gemfile

Slide 16

Slide 16 text

application_system_test_case.rb require 'test_helper' class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :selenium, using: :chrome, screen_size: [1400, 1400] end

Slide 17

Slide 17 text

require "application_system_test_case" class PostsTest < ApplicationSystemTestCase test "visiting the index" do visit posts_url assert_selector "h1", text: "Post" end end

Slide 18

Slide 18 text

rails test:system Running System Tests

Slide 19

Slide 19 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run SYSTEM TESTING Why did it take 3 years?

Slide 20

Slide 20 text

Integration tests were slowww….

Slide 21

Slide 21 text

No content

Slide 22

Slide 22 text

No content

Slide 23

Slide 23 text

Yo, can you make my system test promise come true?

Slide 24

Slide 24 text

I had never used Capybara before

Slide 25

Slide 25 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run SYSTEM TESTING Guiding Principles

Slide 26

Slide 26 text

1. Optimize for programmer happiness 2. Convention over configuration 3. The menu is omakase 4. No one paradigm 5. Exalt beautiful code 6. Provide sharp knives 7. Value integrated systems 8. Progress over stability 9. Push up a big tent The Rails Doctrine

Slide 27

Slide 27 text

Optimize for programmer happiness

Slide 28

Slide 28 text

require 'test_helper' # set the driver Capybara.current_driver = :selenium # register the driver & browser Capybara.register_driver :selenium do |app| Capybara::Selenium::Driver.new(app, browser: :chrome).tap do |driver| driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*[1400, 1400]) end end # set the server Capybara.server = :puma Capybara.always_include_port = true # register the server Capybara.register_server :puma do |app, port, host| Rack::Handler::Puma.run(app, Port: port, Threads: "0:1") end

Slide 29

Slide 29 text

There is zero configuration required to use Capybara with Rails 5.1

Slide 30

Slide 30 text

require 'test_helper' class ApplicationSystemTestCase < ActionDispatch::SystemTestCase driven_by :selenium, using: :chrome, screen_size: [1400, 1400] end

Slide 31

Slide 31 text

Value integrated systems

Slide 32

Slide 32 text

Rails as a whole now addresses system testing

Slide 33

Slide 33 text

Progress over stability

Slide 34

Slide 34 text

When system tests were merged there were a few known bugs

Slide 35

Slide 35 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run SYSTEM TESTING Implementation & Architecture

Slide 36

Slide 36 text

Config defaults: Why Selenium?

Slide 37

Slide 37 text

Selenium doesn’t require system installs

Slide 38

Slide 38 text

Can see the tests running in the browser

Slide 39

Slide 39 text

Better for beginners learning Rails and Capybara

Slide 40

Slide 40 text

driven_by :selenium Driver Options

Slide 41

Slide 41 text

driven_by :poltergeist Driver Options

Slide 42

Slide 42 text

Config defaults: Why Chrome?

Slide 43

Slide 43 text

Chrome is widely used

Slide 44

Slide 44 text

For awhile, Firefox was broken with Selenium

Slide 45

Slide 45 text

driven_by :selenium, using: :chrome Driver Options

Slide 46

Slide 46 text

driven_by :selenium, using: :firefox Driver Options

Slide 47

Slide 47 text

Driver Options driven_by :selenium, using: :firefox
 screen_size: [1400, 1400]

Slide 48

Slide 48 text

Driver Options driven_by :selenium, using: :firefox
 options: { url: "http://chrome:4444/hub" }

Slide 49

Slide 49 text

Config defaults: Failure Screenshots

Slide 50

Slide 50 text

def after_teardown take_failed_screenshot Capybara.reset_sessions! super end Driver Options

Slide 51

Slide 51 text

test "the page contains users" do visit users_path take_screenshot assert_selector "h1", text: "Arya" end Take a Screenshot

Slide 52

Slide 52 text

Database Cleaner not required

Slide 53

Slide 53 text

Test transaction opens a connection

Slide 54

Slide 54 text

Puma opens a second connection Test transaction opens a connection

Slide 55

Slide 55 text

The first connection can’t see the data inserted on the second connection

Slide 56

Slide 56 text

No content

Slide 57

Slide 57 text

I asked for help from @tenderlove & @matthewd

Slide 58

Slide 58 text

Puma connects on the same connection Test transaction opens a connection

Slide 59

Slide 59 text

Plumbing

Slide 60

Slide 60 text

# In actionpack/lib/action_dispatch/system_test_case.rb module ActionDispatch class SystemTestCase < IntegrationTest def initialize(*) # :nodoc: super self.class.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end

Slide 61

Slide 61 text

# In actionpack/lib/action_dispatch/system_test_case.rb module ActionDispatch class SystemTestCase < IntegrationTest def initialize(*) # :nodoc: super self.class.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end

Slide 62

Slide 62 text

# In actionpack/lib/action_dispatch/system_test_case.rb module ActionDispatch class SystemTestCase < IntegrationTest def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run end […]

Slide 63

Slide 63 text

# In actionpack/lib/action_dispatch/system_test_case.rb module ActionDispatch class SystemTestCase < IntegrationTest def self.driven_by(driver, using: :chrome, screen_size: [1400, 1400], options: {}) @driver = SystemTesting::Driver.new(driver, using: using, screen_size: screen_size) end driven_by :selenium end SystemTestCase.start_application end

Slide 64

Slide 64 text

# In action_dispatch/system_testing/driver.rb module ActionDispatch module SystemTesting class Driver # :nodoc: def initialize(name, **options) @name = name @browser = options[:using] @screen_size = options[:screen_size] @options = options[:options] end def use register if selenium? setup end

Slide 65

Slide 65 text

# In actionpack/lib/action_dispatch/system_test_case.rb module ActionDispatch class SystemTestCase < IntegrationTest def initialize(*) # :nodoc: super self.class.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end

Slide 66

Slide 66 text

# In action_dispatch/system_testing/driver.rb module ActionDispatch module SystemTesting class Driver # :nodoc: def use register if selenium? setup end private def selenium? @name == :selenium end […]

Slide 67

Slide 67 text

# In action_dispatch/system_testing/driver.rb def register Capybara.register_driver @name do |app| Capybara::Selenium::Driver.new(app, { browser: @browser }.merge(@options)) .tap do |driver| driver.browser.manage.window.size = Selenium::WebDriver::Dimension.new(*@screen_size) end end end

Slide 68

Slide 68 text

# In action_dispatch/system_testing/driver.rb module ActionDispatch module SystemTesting class Driver # :nodoc: def use register if selenium? setup end private def selenium? @name == :selenium end […]

Slide 69

Slide 69 text

# In action_dispatch/system_testing/driver.rb module ActionDispatch module SystemTesting class Driver # :nodoc: private def setup Capybara.current_driver = @name end end end end

Slide 70

Slide 70 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run BUILDING Open Source Features

Slide 71

Slide 71 text

Public Work

Slide 72

Slide 72 text

Feels like everyone is judging you

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

Stakeholders

Slide 75

Slide 75 text

No content

Slide 76

Slide 76 text

No content

Slide 77

Slide 77 text

$%&' ()*+ ,-./

Slide 78

Slide 78 text

$%&' ()*+ ,-./ 70

Slide 79

Slide 79 text

$%&' ()*+ ,-./

Slide 80

Slide 80 text

$%&' ()*+ ,-./ Perfect?

Slide 81

Slide 81 text

Respecting multiple stakeholders

Slide 82

Slide 82 text

Manage expectations

Slide 83

Slide 83 text

Know who you are building the feature for

Slide 84

Slide 84 text

Be open to change

Slide 85

Slide 85 text

Open source doesn’t work without contributors

Slide 86

Slide 86 text

Build a foundation for others to work off of

Slide 87

Slide 87 text

Thanks @twapole

Slide 88

Slide 88 text

Thanks @robin850

Slide 89

Slide 89 text

Thanks @mtsmfm & @lucasmazza

Slide 90

Slide 90 text

Thanks @renchap

Slide 91

Slide 91 text

Open source doesn’t work without contributors

Slide 92

Slide 92 text

Open source doesn’t work without you

Slide 93

Slide 93 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run Thank you RailsConf!

Slide 94

Slide 94 text

module ActionDispatch class SystemTestCase < IntegrationTest include Capybara::DSL include Capybara::Minitest::Assertions include SystemTesting::TestHelpers::SetupAndTeardown include SystemTesting::TestHelpers::ScreenshotHelper def initialize(*) # :nodoc: super self.class.superclass.driver.use end def self.start_application # :nodoc: Capybara.app = Rack::Builder.new do map "/" do run Rails.application end end SystemTesting::Server.new.run Find me everywhere @eileencodes