Slide 1

Slide 1 text

֦অ

Slide 2

Slide 2 text

Prathamesh Sonpatki @_cha1tanya

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Pune, India

Slide 5

Slide 5 text

@deccanrubyconf

Slide 6

Slide 6 text

papercall.io/ deccanrubyconf-2016

Slide 7

Slide 7 text

deccanrubyconf.com

Slide 8

Slide 8 text

Rails issues team

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

CodeTriage.com

Slide 12

Slide 12 text

Stickers collector

Slide 13

Slide 13 text

Stickers

Slide 14

Slide 14 text

Do you have stickers?

Slide 15

Slide 15 text

T-Shirts are fine too

Slide 16

Slide 16 text

I have something!

Slide 17

Slide 17 text

Do you have a favourite Open source maintainer?

Slide 18

Slide 18 text

Say Thanks!

Slide 19

Slide 19 text

@Schneems

Slide 20

Slide 20 text

Secrets of Testing Rails 5 apps

Slide 21

Slide 21 text

Delete tests

Slide 22

Slide 22 text

Delete tests

Slide 23

Slide 23 text

Secrets of Testing Rails 5 apps

Slide 24

Slide 24 text

Running tests

Slide 25

Slide 25 text

rake test Rails 4

Slide 26

Slide 26 text

Test output matters!

Slide 27

Slide 27 text

Test output matters!

Slide 28

Slide 28 text

Test output matters!

Slide 29

Slide 29 text

$ be rake test test/controllers/users_controller_test.rb Run options: --seed 8322 1) Failure: UsersControllerTest#test_contact_info_successfully_renders_page [railsconf_talk/test/controllers/users_controller_test.rb:9]: # didn't change by 1. Expected: 20 Actual: 19 Rails 4

Slide 30

Slide 30 text

$ be rake test test/controllers/users_controller_test.rb Run options: --seed 8322 1) Failure: UsersControllerTest#test_contact_info_successfully_renders_page [railsconf_talk/test/controllers/users_controller_test.rb:9]: # didn't change by 1. Expected: 20 Actual: 19 Rails 4

Slide 31

Slide 31 text

$ be rake test test/controllers/users_controller_test.rb:9 Rails 4

Slide 32

Slide 32 text

$ be rake test test/controllers/users_controller_test.rb:9 rake aborted! Don't know how to build task 'test/controllers/ users_controller_test.rb:9' (See full trace by running task with --trace) Rails 4

Slide 33

Slide 33 text

Show me what failed?

Slide 34

Slide 34 text

Show me quickly!

Slide 35

Slide 35 text

Which tests were slow?

Slide 36

Slide 36 text

No content

Slide 37

Slide 37 text

But it’s possible

Slide 38

Slide 38 text

Because minitest!

Slide 39

Slide 39 text

Discoverability ?

Slide 40

Slide 40 text

No content

Slide 41

Slide 41 text

Documentation ?

Slide 42

Slide 42 text

$ bin/rake -T test rake test # Runs all tests in test folder rake test:all # Run tests quickly by merging all types and not resetting db rake test:all:db # Run tests quickly, but also reset db rake test:db # Run tests quickly, but also reset db Rails 4

Slide 43

Slide 43 text

$ rails Usage: rails COMMAND [ARGS] The most common rails commands are: generate Generate new code (short-cut alias: "g") console Start the Rails console (short-cut alias: "c") server Start the Rails server (short-cut alias: "s") dbconsole Start a console for the database specified in config/database.yml (short-cut alias: "db") new Create a new Rails application. "rails new my_app" creates a new application called MyApp in "./my_app" In addition to those, there are: destroy Undo code generated with "generate" (short-cut alias: "d") plugin new Generates skeleton for developing a Rails plugin runner Run a piece of code in the application environment (short-cut alias: "r") All commands can be run with -h (or --help) for more information. Rails 4

Slide 44

Slide 44 text

Many libraries trying to solve same problem

Slide 45

Slide 45 text

No content

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

Let’s make runing tests in Rails great again

Slide 48

Slide 48 text

https://github.com/rails/rails/pull/18596

Slide 49

Slide 49 text

Test Runner

Slide 50

Slide 50 text

bin/rails test Rails 5

Slide 51

Slide 51 text

$ bin/rails test Run options: --seed 34502 # Running: ....... Finished in 2.437723s, 2.8715 runs/s, 4.9226 assertions/s. 7 runs, 12 assertions, 0 failures, 0 errors, 0 skips Rails 5

Slide 52

Slide 52 text

Documentation

Slide 53

Slide 53 text

$ bin/rails t -h minitest options: -h, --help Display this help. -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake -v, --verbose Verbose. Show progress processing files. -n, --name PATTERN Filter run on /regexp/ or string. Known extensions: rails, pride Usage: bin/rails test [options] [files or directories] You can run a single test by appending a line number to a filename: bin/rails test test/models/user_test.rb:27 You can run multiple files and directories at the same time: bin/rails test test/controllers test/integration/login_test.rb By default test failures and errors are reported inline during a run. Rails options: -e, --environment ENV Run tests in the ENV environment -b, --backtrace Show the complete backtrace -d, --defer-output Output test failures and errors after the test run -f, --fail-fast Abort test run on first failure or error -c, --[no-]color Enable color in the output Rails 5

Slide 54

Slide 54 text

$ bin/rails t -h minitest options: -h, --help Display this help. -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake -v, --verbose Verbose. Show progress processing files. -n, --name PATTERN Filter run on /regexp/ or string. Known extensions: rails, pride Usage: bin/rails test [options] [files or directories] You can run a single test by appending a line number to a filename: bin/rails test test/models/user_test.rb:27 You can run multiple files and directories at the same time: bin/rails test test/controllers test/integration/login_test.rb By default test failures and errors are reported inline during a run. Rails options: -e, --environment ENV Run tests in the ENV environment -b, --backtrace Show the complete backtrace -d, --defer-output Output test failures and errors after the test run -f, --fail-fast Abort test run on first failure or error -c, --[no-]color Enable color in the output Rails 5

Slide 55

Slide 55 text

$ bin/rails t -h minitest options: -h, --help Display this help. -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake -v, --verbose Verbose. Show progress processing files. -n, --name PATTERN Filter run on /regexp/ or string. Known extensions: rails, pride Usage: bin/rails test [options] [files or directories] You can run a single test by appending a line number to a filename: bin/rails test test/models/user_test.rb:27 You can run multiple files and directories at the same time: bin/rails test test/controllers test/integration/login_test.rb By default test failures and errors are reported inline during a run. Rails options: -e, --environment ENV Run tests in the ENV environment -b, --backtrace Show the complete backtrace -d, --defer-output Output test failures and errors after the test run -f, --fail-fast Abort test run on first failure or error -c, --[no-]color Enable color in the output Rails 5

Slide 56

Slide 56 text

Improved filtering of tests

Slide 57

Slide 57 text

Rerun snippets

Slide 58

Slide 58 text

$ bin/rails test test/controllers/posts_controller_test.rb:18 Run options: --seed 5361 # Running: F Failure: PostsControllerTest#test_should_create_post [railsconf_talk/test/ controllers/posts_controller_test.rb:19]: "Post.count" didn't change by 2. Expected: 4 Actual: 3 bin/rails test test/controllers/posts_controller_test.rb:18 Finished in 0.456947s, 2.1884 runs/s, 2.1884 assertions/s. 1 runs, 1 assertions, 1 failures, 0 errors, 0 skips Rails 5

Slide 59

Slide 59 text

$ bin/rails test test/controllers/posts_controller_test.rb:18 Run options: --seed 5361 # Running: F Failure: PostsControllerTest#test_should_create_post [railsconf_talk/test/ controllers/posts_controller_test.rb:19]: "Post.count" didn't change by 2. Expected: 4 Actual: 3 bin/rails test test/controllers/posts_controller_test.rb:18 Finished in 0.456947s, 2.1884 runs/s, 2.1884 assertions/s. 1 runs, 1 assertions, 1 failures, 0 errors, 0 skips Rails 5

Slide 60

Slide 60 text

Running multiple tests

Slide 61

Slide 61 text

$ bin/rails test test/models/user_test.rb:27 test/models/ post_test.rb:42 Rails 5

Slide 62

Slide 62 text

$ bin/rails test test/controllers test/integration Rails 5

Slide 63

Slide 63 text

Improved reporting of failures

Slide 64

Slide 64 text

Fail fast

Slide 65

Slide 65 text

Backtrace

Slide 66

Slide 66 text

Deferred output

Slide 67

Slide 67 text

Colored output

Slide 68

Slide 68 text

$ bin/rails t Run options: --seed 16545 # Running: ...F Failure: PostsControllerTest#test_should_create_post [/Users/ prathamesh/Projects/reproductions/railsconf_talk/test/ controllers/posts_controller_test.rb:19]: "Post.count" didn't change by 2. Expected: 4 Actual: 3 ✨ Rails 5

Slide 69

Slide 69 text

Powered by Minitest 5

Slide 70

Slide 70 text

Rails minitest plugin + Custom reporter

Slide 71

Slide 71 text

Inspirations

Slide 72

Slide 72 text

RSpec mintiest-reporters maxitest m and others &

Slide 73

Slide 73 text

No content

Slide 74

Slide 74 text

✅Durian ✅ Stinky tofu ✅ Other food that can't fit in

Slide 75

Slide 75 text

Writing tests

Slide 76

Slide 76 text

Unit tests Functional tests Integration tests

Slide 77

Slide 77 text

Unit tests Functional tests Integration tests

Slide 78

Slide 78 text

Controller tests

Slide 79

Slide 79 text

What to test in a controller test

Slide 80

Slide 80 text

req —> res

Slide 81

Slide 81 text

req —> res

Slide 82

Slide 82 text

class ArticlesControllerTest < ActionController::TestCase test "should create article" do assert_difference('Article.count') do post :create, article: { title: @article.title } end assert_redirected_to article_path(assigns(:article)) end end Rails 4

Slide 83

Slide 83 text

class ArticlesControllerTest < ActionController::TestCase test "should create article" do assert_difference('Article.count') do post :create, article: { title: @article.title } end assert_redirected_to article_path(assigns(:article)) end end Rails 4

Slide 84

Slide 84 text

class ArticlesControllerTest < ActionController::TestCase test "should create article" do assert_difference('Article.count') do post :create, article: { title: @article.title } end assert_redirected_to article_path(assigns(:article)) end end Rails 4

Slide 85

Slide 85 text

req —> current state

Slide 86

Slide 86 text

Easy

Slide 87

Slide 87 text

But they Lie

Slide 88

Slide 88 text

class ArticlesControllerTest < ActionController::TestCase test "should create article" do assert_difference('Article.count') do assert assigns(:article) post :create, article: { title: @article.title } end assert_redirected_to article_path(assigns(:article)) end end Rails 4

Slide 89

Slide 89 text

Integration tests

Slide 90

Slide 90 text

class ArticlesIntegrationTest < ActionDispatch::IntegrationTest test "should create article" do assert_difference('Article.count') do post articles_url, params: { article: { title: @article.title } } end assert_redirected_to article_path(Article.last) end end

Slide 91

Slide 91 text

Almost same as controller test

Slide 92

Slide 92 text

And it’s close to real world

Slide 93

Slide 93 text

No content

Slide 94

Slide 94 text

Slow!!

Slide 95

Slide 95 text

Integration controller tests in Rails 5

Slide 96

Slide 96 text

require 'test_helper' class UsersControllerTest < ActionDispatch::IntegrationTest setup do @user = users(:one) end test "should get index" do get users_url assert_response :success end test "should get new" do get new_user_url assert_response :success end test "should create user" do assert_difference('User.count') do post users_url, params: { user: { name: @user.name } } end assert_redirected_to user_path(User.last) end end Rails 5

Slide 97

Slide 97 text

Functional controller tests soft deprecated

Slide 98

Slide 98 text

Old functional tests will continue to work

Slide 99

Slide 99 text

ActionController:: TestCase

Slide 100

Slide 100 text

Might be extracted to a gem in Rails 5.1

Slide 101

Slide 101 text

Implications

Slide 102

Slide 102 text

class ArticlesControllerTest < ActionController::TestCase setup do john = users(:john) session[:user_id] = john.id end end Rails 4

Slide 103

Slide 103 text

class ArticlesControllerTest < ActionController::TestCase setup do john = users(:john) session[:user_id] = john.id end end Rails 4

Slide 104

Slide 104 text

class ArticlesControllerTest < ActionDispatch::IntegrationTest setup do john = users(:john) post login_url, params: {} end end Rails 5

Slide 105

Slide 105 text

class ArticlesControllerTest < ActionDispatch::IntegrationTest setup do john = users(:john) post login_url, params: {} end end Rails 5

Slide 106

Slide 106 text

class ArticlesControllerTest < ActionController::TestCase test ‘index’ do @request.headers["Accept"] = "text/plain, text/html” get :index end end Rails 4

Slide 107

Slide 107 text

class ArticlesControllerTest < ActionDispatch::IntegrationTest test ‘index’ do @request.headers["Accept"] = "text/plain, text/html” get :index end end Rails 4

Slide 108

Slide 108 text

class ArticlesControllerTest < ActionDispatch::IntegrationTest test ‘index’ do @request.headers["Accept"] = "text/plain, text/html” get :index end end # NoMethodError: undefined method `headers' for nil:NilClass Rails 5

Slide 109

Slide 109 text

class ArticlesControllerTest < ActionDispatch::IntegrationTest test ‘index’ do get :index, headers: { accept: "text/plain, text/html” } end end Rails 5

Slide 110

Slide 110 text

Controller tests == Integration tests Rails 5

Slide 111

Slide 111 text

What not to test in a controller test?

Slide 112

Slide 112 text

Don’t test controller internals

Slide 113

Slide 113 text

test "repos" do get :index assert_response :success, 'successfully renders index' assert_not_nil assigns(:repos), 'assigns to repos' assert_not_nil assigns(:repos_subs), 'assigns to repos_subs' assert_template :index, 'render index template' end Rails 4

Slide 114

Slide 114 text

test "repos" do get :index assert_response :success, 'successfully renders index' assert_not_nil assigns(:repos), 'assigns to repos' assert_not_nil assigns(:repos_subs), 'assigns to repos_subs' assert_template :index, 'render index template' end Rails 4

Slide 115

Slide 115 text

test "repos" do get :index assert_response :success, 'successfully renders index' assert_not_nil assigns(:repos), 'assigns to repos' assert_not_nil assigns(:repos_subs), 'assigns to repos_subs' assert_template :index, 'render index template' end Rails 4

Slide 116

Slide 116 text

def index @repos = Repo.all @repo_subs = Repo.first.repo_subs end Rails 4

Slide 117

Slide 117 text

Scratching the surface

Slide 118

Slide 118 text

test "repos" do get :index assert_response :success, 'successfully renders index' assert_select ".repo-item-title", text: 'issue_triage_sandbox' end Rails 5

Slide 119

Slide 119 text

test "repos" do get :index assert_response :success, 'successfully renders index' assert_select ".repo-item-title", text: 'issue_triage_sandbox' end #=> Repo.first.name = ‘issue_triage_sandbox’ Rails 5

Slide 120

Slide 120 text

gem ‘rails-dom-testing’

Slide 121

Slide 121 text

Not just testing controller action in isolation

Slide 122

Slide 122 text

End to end testing

Slide 123

Slide 123 text

Controller View interface

Slide 124

Slide 124 text

Controller View interface

Slide 125

Slide 125 text

Just an implementation detail

Slide 126

Slide 126 text

Deprecated assert_template assigns

Slide 127

Slide 127 text

BUT

Slide 128

Slide 128 text

Testing controller isolated from views

Slide 129

Slide 129 text

gem ‘rails-controller-testing’

Slide 130

Slide 130 text

Testing Rails 5 apps

Slide 131

Slide 131 text

End to end testing

Slide 132

Slide 132 text

We should talk more about it

Slide 133

Slide 133 text

Much more than this

Slide 134

Slide 134 text

Want to know more about Rails 5?

Slide 135

Slide 135 text

Rails 5 Blog Series blog.bigbinary.com /categories/Rails-5

Slide 136

Slide 136 text

This Week in Rails rails-weekly. ongoodbits.com

Slide 137

Slide 137 text

拽拽 @_cha1tanya