-
Notifications
You must be signed in to change notification settings - Fork 0
/
testing.html
1932 lines (1786 loc) · 155 KB
/
testing.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<!doctype html>
<html dir="ltr" lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Pruebas de Aplicaciones Rails — Ruby on Rails Guides</title>
<link rel="stylesheet" type="text/css" href="stylesheets/style-v2.css" data-turbo-track="reload">
<link rel="stylesheet" type="text/css" href="stylesheets/print-v2.css" media="print">
<link rel="stylesheet" type="text/css" href="stylesheets/highlight-v2.css" data-turbo-track="reload">
<link rel="icon" href="images/favicon.ico" sizes="any">
<link rel="apple-touch-icon" href="images/icon.png">
<script src="javascripts/@hotwired--turbo.js" data-turbo-track="reload"></script>
<script src="javascripts/clipboard.js" data-turbo-track="reload"></script>
<script src="javascripts/guides.js" data-turbo-track="reload"></script>
<meta property="og:title" content="Pruebas de Aplicaciones Rails — Ruby on Rails Guides" />
<meta name="description" content="Pruebas de Aplicaciones RailsEsta guía cubre los mecanismos integrados en Rails para probar tu aplicación.Después de leer esta guía, sabrás: Terminología de pruebas en Rails. Cómo escribir pruebas unitarias, funcionales, de integración y de sistema para tu aplicación. Otros enfoques y complementos populares para pruebas." />
<meta property="og:description" content="Pruebas de Aplicaciones RailsEsta guía cubre los mecanismos integrados en Rails para probar tu aplicación.Después de leer esta guía, sabrás: Terminología de pruebas en Rails. Cómo escribir pruebas unitarias, funcionales, de integración y de sistema para tu aplicación. Otros enfoques y complementos populares para pruebas." />
<meta property="og:locale" content="en_US" />
<meta property="og:site_name" content="Ruby on Rails Guides" />
<meta property="og:image" content="https://avatars.githubusercontent.com/u/4223" />
<meta property="og:type" content="website" />
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Noto+Sans+Arabic:[email protected]&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Heebo:[email protected]&family=Noto+Sans+Arabic:[email protected]&display=swap" rel="stylesheet">
<meta name="theme-color" content="#C81418">
</head>
<body class="guide">
<nav id="topNav" aria-label="Secondary">
<div class="wrapper">
<strong class="more-info-label">Más en <a href="https://rubyonrails.org/">rubyonrails.org:</a> </strong>
<span class="red-button more-info-button">
Más Ruby on Rails
</span>
<ul class="more-info-links s-hidden">
<li class="more-info"><a href="https://rubyonrails.org/blog">Blog</a></li>
<li class="more-info"><a href="https://guides.rubyonrails.org/">Guías</a></li>
<li class="more-info"><a href="https://api.rubyonrails.org/">API</a></li>
<li class="more-info"><a href="https://discuss.rubyonrails.org/">Foro</a></li>
<li class="more-info"><a href="https://github.com/rails/rails">Contribuir en GitHub</a></li>
</ul>
</div>
</nav>
<header id="page_header">
<div class="wrapper clearfix">
<nav id="feature_nav">
<div class="header-logo">
<a href="index.html" title="Regresar a la página principal de Guías para Edge">Guías</a>
<span id="version_switcher">
Versión:
<select class="guides-version">
<option value="https://edgeguides.rubyonrails.org/" selected>Edge</option>
<option value="https://guides.rubyonrails.org/v7.2/">7.2</option>
<option value="https://guides.rubyonrails.org/v7.1/">7.1</option>
<option value="https://guides.rubyonrails.org/v7.0/">7.0</option>
<option value="https://guides.rubyonrails.org/v6.1/">6.1</option>
<option value="https://guides.rubyonrails.org/v6.0/">6.0</option>
<option value="https://guides.rubyonrails.org/v5.2/">5.2</option>
<option value="https://guides.rubyonrails.org/v5.1/">5.1</option>
<option value="https://guides.rubyonrails.org/v5.0/">5.0</option>
<option value="https://guides.rubyonrails.org/v4.2/">4.2</option>
<option value="https://guides.rubyonrails.org/v4.1/">4.1</option>
<option value="https://guides.rubyonrails.org/v4.0/">4.0</option>
<option value="https://guides.rubyonrails.org/v3.2/">3.2</option>
<option value="https://guides.rubyonrails.org/v3.1/">3.1</option>
<option value="https://guides.rubyonrails.org/v3.0/">3.0</option>
<option value="https://guides.rubyonrails.org/v2.3/">2.3</option>
</select>
</span>
</div>
<ul class="nav">
<li><a class="nav-item" id="home_nav" href="https://rubyonrails.org/">Inicio</a></li>
<li class="guides-index guides-index-large">
<a href="index.html" id="guidesMenu" class="guides-index-item nav-item">Índice de Guías</a>
<div id="guides" class="clearfix" style="display: none;">
<hr />
<dl class="guides-section-container">
<div class="guides-section">
<dt>Comienza Aquí</dt>
<dd><a href="getting_started.html">Primeros Pasos con Rails</a></dd>
</div>
<div class="guides-section">
<dt>Modelos</dt>
<dd><a href="active_record_basics.html">Conceptos Básicos de Active Record</a></dd>
<dd><a href="active_record_migrations.html">Migraciones de Active Record</a></dd>
<dd><a href="active_record_validations.html">Validaciones de Active Record</a></dd>
</div>
<div class="guides-section">
<dt>Vistas</dt>
<dd><a href="action_view_overview.html">Resumen de Action View</a></dd>
<dd><a href="layouts_and_rendering.html">Diseños y Renderizado en Rails</a></dd>
</div>
<div class="guides-section">
<dt>Controladores</dt>
<dd><a href="action_controller_overview.html">Resumen de Action Controller</a></dd>
<dd><a href="routing.html">Enrutamiento en Rails desde el Exterior</a></dd>
</div>
<div class="guides-section">
<dt>Otros Componentes</dt>
<dd><a href="active_support_core_extensions.html">Extensiones Básicas de Active Support</a></dd>
<dd><a href="action_mailer_basics.html">Conceptos Básicos de Action Mailer</a></dd>
<dd><a href="action_mailbox_basics.html">Conceptos Básicos de Action Mailbox</a></dd>
<dd><a href="action_text_overview.html">Resumen de Action Text</a></dd>
<dd><a href="active_job_basics.html">Conceptos Básicos de Active Job</a></dd>
</div>
<div class="guides-section">
<dt>Políticas</dt>
<dd><a href="maintenance_policy.html">Política de Mantenimiento</a></dd>
</div>
<div class="guides-section">
<dt>Notas de Lanzamiento</dt>
<dd><a href="upgrading_ruby_on_rails.html">Actualizando Ruby on Rails</a></dd>
<dd><a href="7_2_release_notes.html">Versión 7.2 - ?</a></dd>
<dd><a href="7_1_release_notes.html">Versión 7.1 - Octubre 2023</a></dd>
<dd><a href="7_0_release_notes.html">Versión 7.0 - Diciembre 2021</a></dd>
<dd><a href="6_1_release_notes.html">Versión 6.1 - Diciembre 2020</a></dd>
</div>
</dl>
</div>
</li>
<li><a class="nav-item" href="contributing_to_ruby_on_rails.html">Contribuir</a></li>
<li class="guides-index guides-index-small">
<select class="guides-index-item nav-item">
<option value="index.html">Índice de Guías</option>
<optgroup label="Comienza Aquí">
<option value="getting_started.html">Primeros Pasos con Rails</option>
</optgroup>
<optgroup label="Modelos">
<option value="active_record_basics.html">Conceptos Básicos de Active Record</option>
<option value="active_record_migrations.html">Migraciones de Active Record</option>
<option value="active_record_validations.html">Validaciones de Active Record</option>
</optgroup>
<optgroup label="Vistas">
<option value="action_view_overview.html">Resumen de Action View</option>
<option value="layouts_and_rendering.html">Diseños y Renderizado en Rails</option>
</optgroup>
<optgroup label="Controladores">
<option value="action_controller_overview.html">Resumen de Action Controller</option>
<option value="routing.html">Enrutamiento en Rails desde el Exterior</option>
</optgroup>
<optgroup label="Otros Componentes">
<option value="active_support_core_extensions.html">Extensiones Básicas de Active Support</option>
<option value="action_mailer_basics.html">Conceptos Básicos de Action Mailer</option>
<option value="action_mailbox_basics.html">Conceptos Básicos de Action Mailbox</option>
<option value="action_text_overview.html">Resumen de Action Text</option>
<option value="active_job_basics.html">Conceptos Básicos de Active Job</option>
</optgroup>
<optgroup label="Políticas">
<option value="maintenance_policy.html">Política de Mantenimiento</option>
</optgroup>
<optgroup label="Notas de Lanzamiento">
<option value="upgrading_ruby_on_rails.html">Actualizando Ruby on Rails</option>
<option value="7_2_release_notes.html">Versión 7.2 - ?</option>
<option value="7_1_release_notes.html">Versión 7.1 - Octubre 2023</option>
<option value="7_0_release_notes.html">Versión 7.0 - Diciembre 2021</option>
<option value="6_1_release_notes.html">Versión 6.1 - Diciembre 2020</option>
</optgroup>
</select>
</li>
</ul>
</nav>
</div>
</header>
<hr class="hide" />
<section id="feature">
<div class="wrapper">
<h1>Pruebas de Aplicaciones Rails</h1><p>Esta guía cubre los mecanismos integrados en Rails para probar tu aplicación.</p><p>Después de leer esta guía, sabrás:</p>
<ul>
<li>Terminología de pruebas en Rails.</li>
<li>Cómo escribir pruebas unitarias, funcionales, de integración y de sistema para tu aplicación.</li>
<li>Otros enfoques y complementos populares para pruebas.</li>
</ul>
<nav id="subCol">
<h3 class="chapter">
<picture>
<!-- Using the `source` HTML tag to set the dark theme image -->
<source
srcset="images/icon_book-close-bookmark-1-wht.svg"
media="(prefers-color-scheme: dark)"
/>
<img src="images/icon_book-close-bookmark-1.svg" alt="Chapter Icon" />
</picture>
Chapters
</h3>
<ol class="chapters">
<li><a href="#¿por-qué-escribir-pruebas-para-tus-aplicaciones-rails-questionmark">¿Por qué escribir pruebas para tus aplicaciones Rails?</a></li>
<li><a href="#introducción-a-las-pruebas">Introducción a las Pruebas</a>
<ul>
<li><a href="#rails-se-prepara-para-las-pruebas-desde-el-principio">Rails se prepara para las pruebas desde el principio</a></li>
<li><a href="#el-entorno-de-pruebas">El Entorno de Pruebas</a></li>
<li><a href="#rails-se-encuentra-con-minitest">Rails se encuentra con Minitest</a></li>
<li><a href="#afirmaciones-disponibles">Afirmaciones Disponibles</a></li>
<li><a href="#afirmaciones-específicas-de-rails">Afirmaciones Específicas de Rails</a></li>
<li><a href="#una-breve-nota-sobre-los-casos-de-prueba">Una Breve Nota sobre los Casos de Prueba</a></li>
<li><a href="#transacciones">Transacciones</a></li>
<li><a href="#el-ejecutor-de-pruebas-de-rails">El Ejecutor de Pruebas de Rails</a></li>
<li><a href="#ejecutando-pruebas-en-integración-continua-ci">Ejecutando pruebas en Integración Continua (CI)</a></li>
</ul></li>
<li><a href="#pruebas-paralelas">Pruebas Paralelas</a>
<ul>
<li><a href="#pruebas-paralelas-con-procesos">Pruebas Paralelas con Procesos</a></li>
<li><a href="#pruebas-paralelas-con-hilos">Pruebas Paralelas con Hilos</a></li>
<li><a href="#pruebas-de-transacciones-paralelas">Pruebas de Transacciones Paralelas</a></li>
<li><a href="#umbral-para-paralelizar-pruebas">Umbral para paralelizar pruebas</a></li>
</ul></li>
<li><a href="#la-base-de-datos-de-prueba">La Base de Datos de Prueba</a>
<ul>
<li><a href="#manteniendo-el-esquema-de-la-base-de-datos-de-prueba">Manteniendo el Esquema de la Base de Datos de Prueba</a></li>
<li><a href="#lo-básico-sobre-los-fixtures">Lo Básico sobre los Fixtures</a></li>
</ul></li>
<li><a href="#pruebas-de-modelo">Pruebas de Modelo</a></li>
<li><a href="#pruebas-de-sistema">Pruebas de Sistema</a>
<ul>
<li><a href="#cambiando-la-configuración-predeterminada">Cambiando la Configuración Predeterminada</a></li>
<li><a href="#ayudante-de-captura-de-pantalla">Ayudante de Captura de Pantalla</a></li>
<li><a href="#implementando-una-prueba-de-sistema">Implementando una Prueba de Sistema</a></li>
</ul></li>
<li><a href="#pruebas-de-integración">Pruebas de Integración</a>
<ul>
<li><a href="#ayudantes-disponibles-para-pruebas-de-integración">Ayudantes Disponibles para Pruebas de Integración</a></li>
<li><a href="#implementando-una-prueba-de-integración">Implementando una Prueba de Integración</a></li>
</ul></li>
<li><a href="#pruebas-funcionales-para-tus-controladores">Pruebas Funcionales para tus Controladores</a>
<ul>
<li><a href="#qué-incluir-en-tus-pruebas-funcionales">Qué Incluir en tus Pruebas Funcionales</a></li>
<li><a href="#tipos-de-solicitud-disponibles-para-pruebas-funcionales">Tipos de Solicitud Disponibles para Pruebas Funcionales</a></li>
<li><a href="#probando-solicitudes-xhr-ajax">Probando Solicitudes XHR (Ajax)</a></li>
<li><a href="#los-tres-hashes-del-apocalipsis">Los Tres Hashes del Apocalipsis</a></li>
<li><a href="#variables-de-instancia-disponibles">Variables de Instancia Disponibles</a></li>
<li><a href="#estableciendo-encabezados-y-variables-cgi">Estableciendo Encabezados y Variables CGI</a></li>
<li><a href="#probando-avisos-de-flash">Probando Avisos de <code>flash</code></a></li>
<li><a href="#juntándolo-todo">Juntándolo Todo</a></li>
<li><a href="#ayudantes-de-prueba">Ayudantes de Prueba</a></li>
</ul></li>
</ol>
</nav>
<hr>
</div>
</section>
<main id="container">
<div class="wrapper">
<div id="mainCol">
<h2 id="¿por-qué-escribir-pruebas-para-tus-aplicaciones-rails-questionmark"><a class="anchorlink" href="#¿por-qué-escribir-pruebas-para-tus-aplicaciones-rails-questionmark"><span>1</span> ¿Por qué escribir pruebas para tus aplicaciones Rails?</a></h2><p>Rails facilita enormemente la escritura de tus pruebas. Comienza produciendo código de prueba esqueleto mientras creas tus modelos y controladores.</p><p>Al ejecutar tus pruebas de Rails puedes asegurarte de que tu código se adhiera a la funcionalidad deseada incluso después de una importante refactorización del código.</p><p>Las pruebas de Rails también pueden simular solicitudes de navegador y así puedes probar la respuesta de tu aplicación sin tener que probarla a través de tu navegador.</p><h2 id="introducción-a-las-pruebas"><a class="anchorlink" href="#introducción-a-las-pruebas"><span>2</span> Introducción a las Pruebas</a></h2><p>El soporte para pruebas fue integrado en el tejido de Rails desde el principio. No fue una epifanía de "oh! agreguemos soporte para ejecutar pruebas porque son nuevas y geniales".</p><h3 id="rails-se-prepara-para-las-pruebas-desde-el-principio"><a class="anchorlink" href="#rails-se-prepara-para-las-pruebas-desde-el-principio"><span>2.1</span> Rails se prepara para las pruebas desde el principio</a></h3><p>Rails crea un directorio <code>test</code> para ti tan pronto como creas un proyecto Rails usando <code>rails new</code> <em>nombre_de_aplicación</em>. Si listas los contenidos de este directorio, verás:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">ls</span> <span class="nt">-F</span> <span class="nb">test</span>
<span class="go">application_system_test_case.rb controllers/ helpers/ mailers/ system/
channels/ fixtures/ integration/ models/ test_helper.rb
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="ls -F test
">Copy</button>
</div>
<p>Los directorios <code>helpers</code>, <code>mailers</code> y <code>models</code> están destinados a contener pruebas para ayudantes de vista, mailers y modelos, respectivamente. El directorio <code>channels</code> está destinado a contener pruebas para la conexión y canales de Action Cable. El directorio <code>controllers</code> está destinado a contener pruebas para controladores, rutas y vistas. El directorio <code>integration</code> está destinado a contener pruebas para interacciones entre controladores.</p><p>El directorio de pruebas del sistema contiene pruebas del sistema, que se utilizan para pruebas completas del navegador de tu aplicación. Las pruebas del sistema te permiten probar tu aplicación de la manera en que tus usuarios la experimentan y también te ayudan a probar tu JavaScript. Las pruebas del sistema heredan de Capybara y realizan pruebas en el navegador para tu aplicación.</p><p>Los fixtures son una forma de organizar los datos de prueba; residen en el directorio <code>fixtures</code>.</p><p>También se creará un directorio <code>jobs</code> cuando se genere por primera vez una prueba asociada.</p><p>El archivo <code>test_helper.rb</code> contiene la configuración predeterminada para tus pruebas.</p><p>El archivo <code>application_system_test_case.rb</code> contiene la configuración predeterminada para tus pruebas del sistema.</p><h3 id="el-entorno-de-pruebas"><a class="anchorlink" href="#el-entorno-de-pruebas"><span>2.2</span> El Entorno de Pruebas</a></h3><p>Por defecto, cada aplicación Rails tiene tres entornos: desarrollo, prueba y producción.</p><p>La configuración de cada entorno se puede modificar de manera similar. En este caso, podemos modificar nuestro entorno de prueba cambiando las opciones que se encuentran en <code>config/environments/test.rb</code>.</p><p>NOTA: Tus pruebas se ejecutan bajo <code>RAILS_ENV=test</code>.</p><h3 id="rails-se-encuentra-con-minitest"><a class="anchorlink" href="#rails-se-encuentra-con-minitest"><span>2.3</span> Rails se encuentra con Minitest</a></h3><p>Si recuerdas, usamos el comando <code>bin/rails generate model</code> en la guía
<a href="getting_started.html">Comenzando con Rails</a>. Creamos nuestro primer modelo, y entre otras cosas, creó plantillas de prueba en el directorio <code>test</code>:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails </span>generate model article title:string body:text
<span class="c">...
</span><span class="go">create app/models/article.rb
create test/models/article_test.rb
create test/fixtures/articles.yml
</span><span class="c">...
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails generate model article title:string body:text
">Copy</button>
</div>
<p>La plantilla de prueba predeterminada en <code>test/models/article_test.rb</code> se ve así:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">require</span> <span class="s2">"test_helper"</span>
<span class="k">class</span> <span class="nc">ArticleTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="c1"># test "the truth" do</span>
<span class="c1"># assert true</span>
<span class="c1"># end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="require "test_helper"
class ArticleTest < ActiveSupport::TestCase
# test "the truth" do
# assert true
# end
end
">Copy</button>
</div>
<p>Un examen línea por línea de este archivo te ayudará a orientarte en el código y la terminología de pruebas de Rails.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">require</span> <span class="s2">"test_helper"</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="require "test_helper"
">Copy</button>
</div>
<p>Al requerir este archivo, <code>test_helper.rb</code>, se carga la configuración predeterminada para ejecutar nuestras pruebas. Incluiremos esto con todas las pruebas que escribamos, por lo que cualquier método agregado a este archivo estará disponible para todas nuestras pruebas.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ArticleTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="c1"># ...</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ArticleTest < ActiveSupport::TestCase
# ...
end
">Copy</button>
</div>
<p>La clase <code>ArticleTest</code> define un <em>caso de prueba</em> porque hereda de <code>ActiveSupport::TestCase</code>. <code>ArticleTest</code> tiene así todos los métodos disponibles de <code>ActiveSupport::TestCase</code>. Más adelante en esta guía, veremos algunos de los métodos que nos proporciona.</p><p>Cualquier método definido dentro de una clase heredada de <code>Minitest::Test</code> (que es la superclase de <code>ActiveSupport::TestCase</code>) que comience con <code>test_</code> se llama simplemente una prueba. Por lo tanto, los métodos definidos como <code>test_password</code> y <code>test_valid_password</code> son nombres de prueba legales y se ejecutan automáticamente cuando se ejecuta el caso de prueba.</p><p>Rails también agrega un método <code>test</code> que toma un nombre de prueba y un bloque. Genera una prueba normal de <code>Minitest::Unit</code> con nombres de método prefijados con <code>test_</code>. Así que no tienes que preocuparte por nombrar los métodos, y puedes escribir algo como:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">test</span> <span class="s2">"the truth"</span> <span class="k">do</span>
<span class="n">assert</span> <span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="test "the truth" do
assert true
end
">Copy</button>
</div>
<p>Lo cual es aproximadamente lo mismo que escribir esto:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">def</span> <span class="nf">test_the_truth</span>
<span class="n">assert</span> <span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="def test_the_truth
assert true
end
">Copy</button>
</div>
<p>Aunque aún puedes usar definiciones de métodos regulares, usar la macro <code>test</code> permite un nombre de prueba más legible.</p><p>NOTA: El nombre del método se genera reemplazando espacios con guiones bajos. Sin embargo, el resultado no necesita ser un identificador Ruby válido: el nombre puede contener caracteres de puntuación, etc. Eso se debe a que, técnicamente, en Ruby cualquier cadena puede ser un nombre de método. Esto puede requerir el uso de llamadas a <code>define_method</code> y <code>send</code> para funcionar correctamente, pero formalmente hay pocas restricciones sobre el nombre.</p><p>A continuación, veamos nuestra primera afirmación:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">assert</span> <span class="kp">true</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="assert true
">Copy</button>
</div>
<p>Una afirmación es una línea de código que evalúa un objeto (o expresión) para obtener resultados esperados. Por ejemplo, una afirmación puede verificar:</p>
<ul>
<li>¿este valor = ese valor?</li>
<li>¿es este objeto nulo?</li>
<li>¿esta línea de código lanza una excepción?</li>
<li>¿es la contraseña del usuario mayor de 5 caracteres?</li>
</ul>
<p>Cada prueba puede contener una o más afirmaciones, sin restricción sobre cuántas afirmaciones se permiten. Solo cuando todas las afirmaciones son exitosas, la prueba pasará.</p><h4 id="tu-primera-prueba-fallida"><a class="anchorlink" href="#tu-primera-prueba-fallida"><span>2.3.1</span> Tu Primera Prueba Fallida</a></h4><p>Para ver cómo se informa un fallo en la prueba, puedes agregar una prueba fallida al caso de prueba <code>article_test.rb</code>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">test</span> <span class="s2">"should not save article without title"</span> <span class="k">do</span>
<span class="n">article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span>
<span class="n">assert_not</span> <span class="n">article</span><span class="p">.</span><span class="nf">save</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="test "should not save article without title" do
article = Article.new
assert_not article.save
end
">Copy</button>
</div>
<p>Ejecutemos esta prueba recién agregada (donde <code>6</code> es el número de línea donde se define la prueba).</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb:6
<span class="go">Run options: --seed 44656
</span><span class="gp">#</span><span class="w"> </span>Running:
<span class="go">
F
Failure:
</span><span class="gp">ArticleTest#</span>test_should_not_save_article_without_title <span class="o">[</span>/path/to/blog/test/models/article_test.rb:6]:
<span class="go">Expected true to be nil or false
bin/rails test test/models/article_test.rb:6
Finished in 0.023918s, 41.8090 runs/s, 41.8090 assertions/s.
1 runs, 1 assertions, 1 failures, 0 errors, 0 skips
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb:6
">Copy</button>
</div>
<p>En la salida, <code>F</code> denota un fallo. Puedes ver el rastro correspondiente que se muestra bajo <code>Failure</code> junto con el nombre de la prueba fallida. Las siguientes líneas contienen el rastro de la pila seguido de un mensaje que menciona el valor real y el valor esperado por la afirmación. Los mensajes de afirmación predeterminados proporcionan suficiente información para ayudar a identificar el error. Para hacer que el mensaje de fallo de la afirmación sea más legible, cada afirmación proporciona un parámetro de mensaje opcional, como se muestra aquí:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">test</span> <span class="s2">"should not save article without title"</span> <span class="k">do</span>
<span class="n">article</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">new</span>
<span class="n">assert_not</span> <span class="n">article</span><span class="p">.</span><span class="nf">save</span><span class="p">,</span> <span class="s2">"Saved the article without a title"</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="test "should not save article without title" do
article = Article.new
assert_not article.save, "Saved the article without a title"
end
">Copy</button>
</div>
<p>Ejecutar esta prueba muestra el mensaje de afirmación más amigable:</p><div class="interstitial code">
<pre><code class="highlight plaintext">Failure:
ArticleTest#test_should_not_save_article_without_title [/path/to/blog/test/models/article_test.rb:6]:
Saved the article without a title
</code></pre>
<button class="clipboard-button" data-clipboard-text="Failure:
ArticleTest#test_should_not_save_article_without_title [/path/to/blog/test/models/article_test.rb:6]:
Saved the article without a title
">Copy</button>
</div>
<p>Ahora, para que esta prueba pase, podemos agregar una validación a nivel de modelo para el campo <em>title</em>.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">Article</span> <span class="o"><</span> <span class="no">ApplicationRecord</span>
<span class="n">validates</span> <span class="ss">:title</span><span class="p">,</span> <span class="ss">presence: </span><span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class Article < ApplicationRecord
validates :title, presence: true
end
">Copy</button>
</div>
<p>Ahora la prueba debería pasar. Verifiquemos ejecutando la prueba nuevamente:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb:6
<span class="go">Run options: --seed 31252
</span><span class="gp">#</span><span class="w"> </span>Running:
<span class="go">
</span><span class="c">.
</span><span class="go">
Finished in 0.027476s, 36.3952 runs/s, 36.3952 assertions/s.
1 runs, 1 assertions, 0 failures, 0 errors, 0 skips
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb:6
">Copy</button>
</div>
<p>Ahora, si te diste cuenta, primero escribimos una prueba que falla para una funcionalidad deseada, luego escribimos un poco de código que agrega la funcionalidad y finalmente nos aseguramos de que nuestra prueba pase. Este enfoque para el desarrollo de software se conoce como <a href="http://c2.com/cgi/wiki?TestDrivenDevelopment"><em>Desarrollo Basado en Pruebas</em> (TDD)</a>.</p><h4 id="cómo-se-ve-un-error"><a class="anchorlink" href="#cómo-se-ve-un-error"><span>2.3.2</span> Cómo se ve un Error</a></h4><p>Para ver cómo se informa un error, aquí hay una prueba que contiene un error:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">test</span> <span class="s2">"should report error"</span> <span class="k">do</span>
<span class="c1"># some_undefined_variable no está definida en otra parte del caso de prueba</span>
<span class="n">some_undefined_variable</span>
<span class="n">assert</span> <span class="kp">true</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="test "should report error" do
# some_undefined_variable no está definida en otra parte del caso de prueba
some_undefined_variable
assert true
end
">Copy</button>
</div>
<p>Ahora puedes ver aún más salida en la consola al ejecutar las pruebas:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb
<span class="go">Run options: --seed 1808
</span><span class="gp">#</span><span class="w"> </span>Running:
<span class="go">
.E
Error:
</span><span class="gp">ArticleTest#</span>test_should_report_error:
<span class="gp">NameError: undefined local variable or method 'some_undefined_variable' for #</span><ArticleTest:0x007fee3aa71798>
<span class="gp"> test/models/article_test.rb:11:in 'block in <class:ArticleTest></span><span class="s1">'
</span><span class="go">
bin/rails test test/models/article_test.rb:9
Finished in 0.040609s, 49.2500 runs/s, 24.6250 assertions/s.
2 runs, 1 assertions, 0 failures, 1 errors, 0 skips
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb
">Copy</button>
</div>
<p>Observa la 'E' en la salida. Denota una prueba con error.</p><p>NOTA: La ejecución de cada método de prueba se detiene tan pronto como se encuentra un error o un fallo en la afirmación, y el conjunto de pruebas continúa con el siguiente método. Todos los métodos de prueba se ejecutan en orden aleatorio. La opción <a href="configuring.html#config-active-support-test-order"><code>config.active_support.test_order</code></a> se puede usar para configurar el orden de las pruebas.</p><p>Cuando una prueba falla, se te presenta el rastro correspondiente. Por defecto, Rails filtra ese rastro y solo imprimirá líneas relevantes para tu aplicación. Esto elimina el ruido del marco y ayuda a centrarse en tu código. Sin embargo, hay situaciones en las que deseas ver el rastro completo. Establece el argumento <code>-b</code> (o <code>--backtrace</code>) para habilitar este comportamiento:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test</span> <span class="nt">-b</span> <span class="nb">test</span>/models/article_test.rb
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test -b test/models/article_test.rb
">Copy</button>
</div>
<p>Si queremos que esta prueba pase, podemos modificarla para usar <code>assert_raises</code> así:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="nb">test</span> <span class="s2">"should report error"</span> <span class="k">do</span>
<span class="c1"># some_undefined_variable no está definida en otra parte del caso de prueba</span>
<span class="n">assert_raises</span><span class="p">(</span><span class="no">NameError</span><span class="p">)</span> <span class="k">do</span>
<span class="n">some_undefined_variable</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="test "should report error" do
# some_undefined_variable no está definida en otra parte del caso de prueba
assert_raises(NameError) do
some_undefined_variable
end
end
">Copy</button>
</div>
<p>Esta prueba debería pasar ahora.</p><h3 id="afirmaciones-disponibles"><a class="anchorlink" href="#afirmaciones-disponibles"><span>2.4</span> Afirmaciones Disponibles</a></h3><p>Hasta ahora has visto un vistazo de algunas de las afirmaciones que están disponibles. Las afirmaciones son las abejas obreras de las pruebas. Son las que realizan realmente las comprobaciones para asegurarse de que las cosas van según lo planeado.</p><p>Aquí hay un extracto de las afirmaciones que puedes usar con <a href="https://github.com/minitest/minitest"><code>Minitest</code></a>, la biblioteca de pruebas predeterminada utilizada por Rails. El parámetro <code>[msg]</code> es un mensaje de cadena opcional que puedes especificar para hacer más claros los mensajes de fallo de tus pruebas.</p>
<table><thead>
<tr>
<th>Afirmación</th>
<th>Propósito</th>
</tr>
</thead><tbody>
<tr>
<td><code>assert( test, [msg] )</code></td>
<td>Asegura que <code>test</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_not( test, [msg] )</code></td>
<td>Asegura que <code>test</code> es falso.</td>
</tr>
<tr>
<td><code>assert_equal( expected, actual, [msg] )</code></td>
<td>Asegura que <code>expected == actual</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_not_equal( expected, actual, [msg] )</code></td>
<td>Asegura que <code>expected != actual</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_same( expected, actual, [msg] )</code></td>
<td>Asegura que <code>expected.equal?(actual)</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_not_same( expected, actual, [msg] )</code></td>
<td>Asegura que <code>expected.equal?(actual)</code> es falso.</td>
</tr>
<tr>
<td><code>assert_nil( obj, [msg] )</code></td>
<td>Asegura que <code>obj.nil?</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_not_nil( obj, [msg] )</code></td>
<td>Asegura que <code>obj.nil?</code> es falso.</td>
</tr>
<tr>
<td><code>assert_empty( obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> está <code>empty?</code>.</td>
</tr>
<tr>
<td><code>assert_not_empty( obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> no está <code>empty?</code>.</td>
</tr>
<tr>
<td><code>assert_match( regexp, string, [msg] )</code></td>
<td>Asegura que una cadena coincide con la expresión regular.</td>
</tr>
<tr>
<td><code>assert_no_match( regexp, string, [msg] )</code></td>
<td>Asegura que una cadena no coincide con la expresión regular.</td>
</tr>
<tr>
<td><code>assert_includes( collection, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> está en <code>collection</code>.</td>
</tr>
<tr>
<td><code>assert_not_includes( collection, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> no está en <code>collection</code>.</td>
</tr>
<tr>
<td><code>assert_in_delta( expected, actual, [delta], [msg] )</code></td>
<td>Asegura que los números <code>expected</code> y <code>actual</code> están dentro de <code>delta</code> entre sí.</td>
</tr>
<tr>
<td><code>assert_not_in_delta( expected, actual, [delta], [msg] )</code></td>
<td>Asegura que los números <code>expected</code> y <code>actual</code> no están dentro de <code>delta</code> entre sí.</td>
</tr>
<tr>
<td><code>assert_in_epsilon ( expected, actual, [epsilon], [msg] )</code></td>
<td>Asegura que los números <code>expected</code> y <code>actual</code> tienen un error relativo menor que <code>epsilon</code>.</td>
</tr>
<tr>
<td><code>assert_not_in_epsilon ( expected, actual, [epsilon], [msg] )</code></td>
<td>Asegura que los números <code>expected</code> y <code>actual</code> no tienen un error relativo menor que <code>epsilon</code>.</td>
</tr>
<tr>
<td><code>assert_throws( symbol, [msg] ) { block }</code></td>
<td>Asegura que el bloque dado lanza el símbolo.</td>
</tr>
<tr>
<td><code>assert_raises( exception1, exception2, ... ) { block }</code></td>
<td>Asegura que el bloque dado lanza una de las excepciones dadas.</td>
</tr>
<tr>
<td><code>assert_instance_of( class, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> es una instancia de <code>class</code>.</td>
</tr>
<tr>
<td><code>assert_not_instance_of( class, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> no es una instancia de <code>class</code>.</td>
</tr>
<tr>
<td><code>assert_kind_of( class, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> es una instancia de <code>class</code> o desciende de ella.</td>
</tr>
<tr>
<td><code>assert_not_kind_of( class, obj, [msg] )</code></td>
<td>Asegura que <code>obj</code> no es una instancia de <code>class</code> y no desciende de ella.</td>
</tr>
<tr>
<td><code>assert_respond_to( obj, symbol, [msg] )</code></td>
<td>Asegura que <code>obj</code> responde a <code>symbol</code>.</td>
</tr>
<tr>
<td><code>assert_not_respond_to( obj, symbol, [msg] )</code></td>
<td>Asegura que <code>obj</code> no responde a <code>symbol</code>.</td>
</tr>
<tr>
<td><code>assert_operator( obj1, operator, [obj2], [msg] )</code></td>
<td>Asegura que <code>obj1.operator(obj2)</code> es verdadero.</td>
</tr>
<tr>
<td><code>assert_not_operator( obj1, operator, [obj2], [msg] )</code></td>
<td>Asegura que <code>obj1.operator(obj2)</code> es falso.</td>
</tr>
<tr>
<td><code>assert_predicate ( obj, predicate, [msg] )</code></td>
<td>Asegura que <code>obj.predicate</code> es verdadero, por ejemplo, <code>assert_predicate str, :empty?</code></td>
</tr>
<tr>
<td><code>assert_not_predicate ( obj, predicate, [msg] )</code></td>
<td>Asegura que <code>obj.predicate</code> es falso, por ejemplo, <code>assert_not_predicate str, :empty?</code></td>
</tr>
<tr>
<td><code>assert_error_reported(class) { block }</code></td>
<td>Asegura que se ha informado de la clase de error, por ejemplo, <code>assert_error_reported IOError { Rails.error.report(IOError.new("Oops")) }</code></td>
</tr>
<tr>
<td><code>assert_no_error_reported { block }</code></td>
<td>Asegura que no se han informado errores, por ejemplo, <code>assert_no_error_reported { perform_service }</code></td>
</tr>
<tr>
<td><code>flunk( [msg] )</code></td>
<td>Asegura el fallo. Esto es útil para marcar explícitamente una prueba que aún no está terminada.</td>
</tr>
</tbody></table>
<p>Las anteriores son un subconjunto de las afirmaciones que admite minitest. Para una lista exhaustiva y más actualizada, consulta la <a href="http://docs.seattlerb.org/minitest/">documentación de la API de Minitest</a>, específicamente <a href="http://docs.seattlerb.org/minitest/Minitest/Assertions.html"><code>Minitest::Assertions</code></a>.</p><p>Debido a la naturaleza modular del marco de pruebas, es posible crear tus propias afirmaciones. De hecho, eso es exactamente lo que hace Rails. Incluye algunas afirmaciones especializadas para facilitarte la vida.</p><p>NOTA: Crear tus propias afirmaciones es un tema avanzado que no cubriremos en este tutorial.</p><h3 id="afirmaciones-específicas-de-rails"><a class="anchorlink" href="#afirmaciones-específicas-de-rails"><span>2.5</span> Afirmaciones Específicas de Rails</a></h3><p>Rails agrega algunas afirmaciones personalizadas propias al marco <code>minitest</code>:</p>
<table><thead>
<tr>
<th>Afirmación</th>
<th>Propósito</th>
</tr>
</thead><tbody>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_difference)"><code>assert_difference(expressions, difference = 1, message = nil) {...}</code></a></td>
<td>Prueba la diferencia numérica entre el valor de retorno de una expresión como resultado de lo que se evalúa en el bloque generado.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_no_difference"><code>assert_no_difference(expressions, message = nil, &block)</code></a></td>
<td>Asegura que el resultado numérico de evaluar una expresión no cambie antes y después de invocar el bloque pasado.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_changes"><code>assert_changes(expressions, message = nil, from:, to:, &block)</code></a></td>
<td>Prueba que el resultado de evaluar una expresión cambie después de invocar el bloque pasado.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_no_changes"><code>assert_no_changes(expressions, message = nil, &block)</code></a></td>
<td>Prueba que el resultado de evaluar una expresión no cambie después de invocar el bloque pasado.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/Testing/Assertions.html#method-i-assert_nothing_raised"><code>assert_nothing_raised { block }</code></a></td>
<td>Asegura que el bloque dado no arroja ninguna excepción.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_recognizes"><code>assert_recognizes(expected_options, path, extras={}, message=nil)</code></a></td>
<td>Asegura que el enrutamiento de la ruta dada se manejó correctamente y que las opciones analizadas (dadas en el hash expected_options) coinciden con la ruta. Básicamente, asegura que Rails reconoce la ruta dada por expected_options.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Assertions/RoutingAssertions.html#method-i-assert_generates"><code>assert_generates(expected_path, options, defaults={}, extras = {}, message=nil)</code></a></td>
<td>Asegura que las opciones proporcionadas se puedan usar para generar la ruta proporcionada. Este es el inverso de assert_recognizes. El parámetro extras se usa para indicar los nombres y valores de parámetros de solicitud adicionales que estarían en una cadena de consulta. El parámetro message te permite especificar un mensaje de error personalizado para fallos de afirmación.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Assertions/ResponseAssertions.html#method-i-assert_response"><code>assert_response(type, message = nil)</code></a></td>
<td>Asegura que la respuesta venga con un código de estado específico. Puedes especificar <code>:success</code> para indicar 200-299, <code>:redirect</code> para indicar 300-399, <code>:missing</code> para indicar 404, o <code>:error</code> para coincidir con el rango 500-599. También puedes pasar un número de estado explícito o su equivalente simbólico. Para más información, consulta <a href="https://rubydoc.info/gems/rack/Rack/Utils#HTTP_STATUS_CODES-constant">lista completa de códigos de estado</a> y cómo funciona su <a href="https://rubydoc.info/gems/rack/Rack/Utils#SYMBOL_TO_STATUS_CODE-constant">mapeo</a>.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/Assertions/ResponseAssertions.html#method-i-assert_redirected_to"><code>assert_redirected_to(options = {}, message=nil)</code></a></td>
<td>Asegura que la respuesta es una redirección a una URL que coincide con las opciones dadas. También puedes pasar rutas nombradas como <code>assert_redirected_to root_path</code> y objetos Active Record como <code>assert_redirected_to @article</code>.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Assertions/QueryAssertions.html#method-i-assert_queries_count"><code>assert_queries_count(count = nil, include_schema: false, &block)</code></a></td>
<td>Asegura que <code>&block</code> genera un número <code>int</code> de consultas SQL.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Assertions/QueryAssertions.html#method-i-assert_no_queries"><code>assert_no_queries(include_schema: false, &block)</code></a></td>
<td>Asegura que <code>&block</code> no genera consultas SQL.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Assertions/QueryAssertions.html#method-i-assert_queries_match"><code>assert_queries_match(pattern, count: nil, include_schema: false, &block)</code></a></td>
<td>Asegura que <code>&block</code> genera consultas SQL que coinciden con el patrón.</td>
</tr>
<tr>
<td><a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/Assertions/QueryAssertions.html#method-i-assert_no_queries_match"><code>assert_no_queries_match(pattern, &block)</code></a></td>
<td>Asegura que <code>&block</code> no genera consultas SQL que coinciden con el patrón.</td>
</tr>
</tbody></table>
<p>Verás el uso de algunas de estas afirmaciones en el próximo capítulo.</p><h3 id="una-breve-nota-sobre-los-casos-de-prueba"><a class="anchorlink" href="#una-breve-nota-sobre-los-casos-de-prueba"><span>2.6</span> Una Breve Nota sobre los Casos de Prueba</a></h3><p>Todas las afirmaciones básicas como <code>assert_equal</code> definidas en <code>Minitest::Assertions</code> también están disponibles en las clases que usamos en nuestros propios casos de prueba. De hecho, Rails proporciona las siguientes clases para que heredes de ellas:</p>
<ul>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveSupport/TestCase.html"><code>ActiveSupport::TestCase</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActionMailer/TestCase.html"><code>ActionMailer::TestCase</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActionView/TestCase.html"><code>ActionView::TestCase</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActiveJob/TestCase.html"><code>ActiveJob::TestCase</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/IntegrationTest.html"><code>ActionDispatch::IntegrationTest</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/ActionDispatch/SystemTestCase.html"><code>ActionDispatch::SystemTestCase</code></a></li>
<li><a href="https://edgeapi.rubyonrails.org/classes/Rails/Generators/TestCase.html"><code>Rails::Generators::TestCase</code></a></li>
</ul>
<p>Cada una de estas clases incluye <code>Minitest::Assertions</code>, lo que nos permite usar todas las afirmaciones básicas en nuestras pruebas.</p><p>NOTA: Para más información sobre <code>Minitest</code>, consulta <a href="http://docs.seattlerb.org/minitest">su documentación</a>.</p><h3 id="transacciones"><a class="anchorlink" href="#transacciones"><span>2.7</span> Transacciones</a></h3><p>Por defecto, Rails envuelve automáticamente las pruebas en una transacción de base de datos que se revierte después de que terminan. Esto hace que las pruebas sean independientes entre sí y los cambios en la base de datos solo son visibles dentro de una sola prueba.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">MyTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="nb">test</span> <span class="s2">"newly created users are active by default"</span> <span class="k">do</span>
<span class="c1"># Dado que la prueba está implícitamente envuelta en una transacción de base de datos, el usuario</span>
<span class="c1"># creado aquí no será visto por otras pruebas.</span>
<span class="n">assert</span> <span class="no">User</span><span class="p">.</span><span class="nf">create</span><span class="p">.</span><span class="nf">active?</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class MyTest < ActiveSupport::TestCase
test "newly created users are active by default" do
# Dado que la prueba está implícitamente envuelta en una transacción de base de datos, el usuario
# creado aquí no será visto por otras pruebas.
assert User.create.active?
end
end
">Copy</button>
</div>
<p>El método <code>ActiveRecord::Base.current_transaction</code> aún funciona como se espera, sin embargo:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">MyTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="nb">test</span> <span class="s2">"current_transaction"</span> <span class="k">do</span>
<span class="c1"># La transacción implícita alrededor de las pruebas no interfiere con la</span>
<span class="c1"># semántica de nivel de aplicación de current_transaction.</span>
<span class="n">assert</span> <span class="no">User</span><span class="p">.</span><span class="nf">current_transaction</span><span class="p">.</span><span class="nf">blank?</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class MyTest < ActiveSupport::TestCase
test "current_transaction" do
# La transacción implícita alrededor de las pruebas no interfiere con la
# semántica de nivel de aplicación de current_transaction.
assert User.current_transaction.blank?
end
end
">Copy</button>
</div>
<p>Si hay <a href="active_record_multiple_databases.html">múltiples bases de datos de escritura</a> en su lugar, las pruebas se envuelven en tantas transacciones respectivas, y todas ellas se revierten.</p><h4 id="optar-por-no-usar-transacciones-de-prueba"><a class="anchorlink" href="#optar-por-no-usar-transacciones-de-prueba"><span>2.7.1</span> Optar por No Usar Transacciones de Prueba</a></h4><p>Los casos de prueba individuales pueden optar por no usarlas:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">MyTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="c1"># No hay transacción de base de datos implícita que envuelva las pruebas en este caso de prueba.</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">use_transactional_tests</span> <span class="o">=</span> <span class="kp">false</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class MyTest < ActiveSupport::TestCase
# No hay transacción de base de datos implícita que envuelva las pruebas en este caso de prueba.
self.use_transactional_tests = false
end
">Copy</button>
</div>
<h3 id="el-ejecutor-de-pruebas-de-rails"><a class="anchorlink" href="#el-ejecutor-de-pruebas-de-rails"><span>2.8</span> El Ejecutor de Pruebas de Rails</a></h3><p>Podemos ejecutar todas nuestras pruebas a la vez usando el comando <code>bin/rails test</code>.</p><p>O podemos ejecutar un solo archivo de prueba pasando el comando <code>bin/rails test</code> el nombre del archivo que contiene los casos de prueba.</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb
<span class="go">Run options: --seed 1559
</span><span class="gp">#</span><span class="w"> </span>Running:
<span class="go">
</span><span class="c">..
</span><span class="go">
Finished in 0.027034s, 73.9810 runs/s, 110.9715 assertions/s.
2 runs, 3 assertions, 0 failures, 0 errors, 0 skips
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb
">Copy</button>
</div>
<p>Esto ejecutará todos los métodos de prueba del caso de prueba.</p><p>También puedes ejecutar un método de prueba particular del caso de prueba proporcionando la bandera <code>-n</code> o <code>--name</code> y el nombre del método de prueba.</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb <span class="nt">-n</span> test_the_truth
<span class="go">Run options: -n test_the_truth --seed 43583
</span><span class="gp">#</span><span class="w"> </span>Running:
<span class="go">
</span><span class="c">.
</span><span class="go">
Finished tests in 0.009064s, 110.3266 tests/s, 110.3266 assertions/s.
1 tests, 1 assertions, 0 failures, 0 errors, 0 skips
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb -n test_the_truth
">Copy</button>
</div>
<p>También puedes ejecutar una prueba en una línea específica proporcionando el número de línea.</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb:6 <span class="c"># ejecutar prueba específica y línea</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb:6 # ejecutar prueba específica y línea
">Copy</button>
</div>
<p>También puedes ejecutar un rango de pruebas proporcionando el rango de líneas.</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/models/article_test.rb:6-20 <span class="c"># ejecuta pruebas desde la línea 6 hasta la 20</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/models/article_test.rb:6-20 # ejecuta pruebas desde la línea 6 hasta la 20
">Copy</button>
</div>
<p>También puedes ejecutar un directorio completo de pruebas proporcionando la ruta al directorio.</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test test</span>/controllers <span class="c"># ejecutar todas las pruebas de un directorio específico</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test test/controllers # ejecutar todas las pruebas de un directorio específico
">Copy</button>
</div>
<p>El ejecutor de pruebas también proporciona muchas otras características como fallar rápido, diferir la salida de las pruebas al final de la ejecución de la prueba, etc. Consulta la documentación del ejecutor de pruebas de la siguiente manera:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test</span> <span class="nt">-h</span>
<span class="go">Usage:
bin/rails test [PATHS...]
Run tests except system tests
Examples:
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 tests with in a line range by appending the line range to a filename:
bin/rails test test/models/user_test.rb:10-20
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.
minitest options:
-h, --help Display this help.
</span><span class="gp"> --no-plugins Bypass minitest plugin auto-loading (or set $</span>MT_NO_PLUGINS<span class="o">)</span><span class="nb">.</span>
<span class="go"> -s, --seed SEED Sets random seed. Also via env. Eg: SEED=n rake
-v, --verbose Verbose. Show progress processing files.
-q, --quiet Quiet. Show no progress processing files.
--show-skips Show skipped at the end of run.
-n, --name PATTERN Filter run on /regexp/ or string.
--exclude PATTERN Exclude /regexp/ or string from run.
-S, --skip CODES Skip reporting of certain types of results (eg E).
Known extensions: rails, pride
-w, --warnings Run with Ruby warnings enabled
-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
--profile [COUNT] Enable profiling of tests and list the slowest test cases (default: 10)
-p, --pride Pride. Show your testing pride!
</span></code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test -h
">Copy</button>
</div>
<h3 id="ejecutando-pruebas-en-integración-continua-ci"><a class="anchorlink" href="#ejecutando-pruebas-en-integración-continua-ci"><span>2.9</span> Ejecutando pruebas en Integración Continua (CI)</a></h3><p>Para ejecutar todas las pruebas en un entorno CI, solo hay un comando que necesitas:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nb">bin/rails test</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="bin/rails test
">Copy</button>
</div>
<p>Si estás usando <a href="#pruebas-de-sistema">Pruebas de Sistema</a>, <code>bin/rails test</code> no las ejecutará, ya que pueden ser lentas. Para ejecutarlas también, agrega otro paso de CI que ejecute <code>bin/rails test:system</code>, o cambia tu primer paso a <code>bin/rails test:all</code>, que ejecuta todas las pruebas incluidas las pruebas del sistema.</p><h2 id="pruebas-paralelas"><a class="anchorlink" href="#pruebas-paralelas"><span>3</span> Pruebas Paralelas</a></h2><p>Las pruebas paralelas te permiten paralelizar tu conjunto de pruebas. Si bien el método predeterminado es bifurcar procesos, también se admite el uso de hilos. Ejecutar pruebas en paralelo reduce el tiempo que tarda en ejecutarse todo tu conjunto de pruebas.</p><h3 id="pruebas-paralelas-con-procesos"><a class="anchorlink" href="#pruebas-paralelas-con-procesos"><span>3.1</span> Pruebas Paralelas con Procesos</a></h3><p>El método de paralelización predeterminado es bifurcar procesos usando el sistema DRb de Ruby. Los procesos se bifurcan según el número de trabajadores proporcionados. El número predeterminado es el recuento real de núcleos en la máquina en la que te encuentras, pero se puede cambiar por el número pasado al método parallelize.</p><p>Para habilitar la paralelización, agrega lo siguiente a tu <code>test_helper.rb</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ActiveSupport::TestCase</span>
<span class="n">parallelize</span><span class="p">(</span><span class="ss">workers: </span><span class="mi">2</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ActiveSupport::TestCase
parallelize(workers: 2)
end
">Copy</button>
</div>
<p>El número de trabajadores pasado es el número de veces que se bifurcará el proceso. Es posible que desees paralelizar tu conjunto de pruebas local de manera diferente a tu CI, por lo que se proporciona una variable de entorno para poder cambiar fácilmente el número de trabajadores que debe usar una ejecución de prueba:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nv">PARALLEL_WORKERS</span><span class="o">=</span>15 <span class="nb">bin/rails test</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="PARALLEL_WORKERS=15 bin/rails test
">Copy</button>
</div>
<p>Al paralelizar pruebas, Active Record maneja automáticamente la creación de una base de datos y la carga del esquema en la base de datos para cada proceso. Las bases de datos se sufijarán con el número correspondiente al trabajador. Por ejemplo, si tienes 2 trabajadores, las pruebas crearán <code>test-database-0</code> y <code>test-database-1</code> respectivamente.</p><p>Si el número de trabajadores pasado es 1 o menos, los procesos no se bifurcarán y las pruebas no se paralelizarán y usarán la base de datos <code>test-database</code> original.</p><p>Se proporcionan dos ganchos, uno se ejecuta cuando se bifurca el proceso y otro se ejecuta antes de que se cierre el proceso bifurcado. Estos pueden ser útiles si tu aplicación usa múltiples bases de datos o realiza otras tareas que dependen del número de trabajadores.</p><p>El método <code>parallelize_setup</code> se llama justo después de que se bifurcan los procesos. El método <code>parallelize_teardown</code> se llama justo antes de que se cierren los procesos.</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ActiveSupport::TestCase</span>
<span class="n">parallelize_setup</span> <span class="k">do</span> <span class="o">|</span><span class="n">worker</span><span class="o">|</span>
<span class="c1"># configurar bases de datos</span>
<span class="k">end</span>
<span class="n">parallelize_teardown</span> <span class="k">do</span> <span class="o">|</span><span class="n">worker</span><span class="o">|</span>
<span class="c1"># limpiar bases de datos</span>
<span class="k">end</span>
<span class="n">parallelize</span><span class="p">(</span><span class="ss">workers: :number_of_processors</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ActiveSupport::TestCase
parallelize_setup do |worker|
# configurar bases de datos
end
parallelize_teardown do |worker|
# limpiar bases de datos
end
parallelize(workers: :number_of_processors)
end
">Copy</button>
</div>
<p>Estos métodos no son necesarios ni están disponibles cuando se utilizan pruebas paralelas con hilos.</p><h3 id="pruebas-paralelas-con-hilos"><a class="anchorlink" href="#pruebas-paralelas-con-hilos"><span>3.2</span> Pruebas Paralelas con Hilos</a></h3><p>Si prefieres usar hilos o estás usando JRuby, se proporciona una opción de paralelización con hilos. El paralelizador con hilos está respaldado por el <code>Parallel::Executor</code> de Minitest.</p><p>Para cambiar el método de paralelización para usar hilos en lugar de bifurcaciones, coloca lo siguiente en tu <code>test_helper.rb</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ActiveSupport::TestCase</span>
<span class="n">parallelize</span><span class="p">(</span><span class="ss">workers: :number_of_processors</span><span class="p">,</span> <span class="ss">with: :threads</span><span class="p">)</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ActiveSupport::TestCase
parallelize(workers: :number_of_processors, with: :threads)
end
">Copy</button>
</div>
<p>Las aplicaciones Rails generadas desde JRuby o TruffleRuby incluirán automáticamente la opción <code>with: :threads</code>.</p><p>El número de trabajadores pasado a <code>parallelize</code> determina el número de hilos que las pruebas usarán. Es posible que desees paralelizar tu conjunto de pruebas local de manera diferente a tu CI, por lo que se proporciona una variable de entorno para poder cambiar fácilmente el número de trabajadores que debe usar una ejecución de prueba:</p><div class="interstitial code">
<pre><code class="highlight console"><span class="gp">$</span><span class="w"> </span><span class="nv">PARALLEL_WORKERS</span><span class="o">=</span>15 <span class="nb">bin/rails test</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="PARALLEL_WORKERS=15 bin/rails test
">Copy</button>
</div>
<h3 id="pruebas-de-transacciones-paralelas"><a class="anchorlink" href="#pruebas-de-transacciones-paralelas"><span>3.3</span> Pruebas de Transacciones Paralelas</a></h3><p>Cuando deseas probar el código que ejecuta transacciones de base de datos paralelas en hilos, estas pueden bloquearse entre sí porque ya están anidadas bajo la transacción implícita de prueba.</p><p>Para solucionar esto, puedes deshabilitar las transacciones en una clase de caso de prueba configurando <code>self.use_transactional_tests = false</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">WorkerTest</span> <span class="o"><</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">TestCase</span>
<span class="nb">self</span><span class="p">.</span><span class="nf">use_transactional_tests</span> <span class="o">=</span> <span class="kp">false</span>
<span class="nb">test</span> <span class="s2">"parallel transactions"</span> <span class="k">do</span>
<span class="c1"># iniciar algunos hilos que crean transacciones</span>
<span class="k">end</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class WorkerTest < ActiveSupport::TestCase
self.use_transactional_tests = false
test "parallel transactions" do
# iniciar algunos hilos que crean transacciones
end
end
">Copy</button>
</div>
<p>NOTA: Con pruebas transaccionales deshabilitadas, debes limpiar cualquier dato que las pruebas creen ya que los cambios no se revierten automáticamente después de que la prueba se completa.</p><h3 id="umbral-para-paralelizar-pruebas"><a class="anchorlink" href="#umbral-para-paralelizar-pruebas"><span>3.4</span> Umbral para paralelizar pruebas</a></h3><p>Ejecutar pruebas en paralelo agrega una sobrecarga en términos de configuración de la base de datos y carga de fixtures. Debido a esto, Rails no paralelizará ejecuciones que involucren menos de 50 pruebas.</p><p>Puedes configurar este umbral en tu <code>test.rb</code>:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="n">config</span><span class="p">.</span><span class="nf">active_support</span><span class="p">.</span><span class="nf">test_parallelization_threshold</span> <span class="o">=</span> <span class="mi">100</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="config.active_support.test_parallelization_threshold = 100
">Copy</button>
</div>
<p>Y también al configurar la paralelización a nivel del caso de prueba:</p><div class="interstitial code">
<pre><code class="highlight ruby"><span class="k">class</span> <span class="nc">ActiveSupport::TestCase</span>
<span class="n">parallelize</span> <span class="ss">threshold: </span><span class="mi">100</span>
<span class="k">end</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="class ActiveSupport::TestCase
parallelize threshold: 100
end
">Copy</button>
</div>
<h2 id="la-base-de-datos-de-prueba"><a class="anchorlink" href="#la-base-de-datos-de-prueba"><span>4</span> La Base de Datos de Prueba</a></h2><p>Casi todas las aplicaciones Rails interactúan mucho con una base de datos y, como resultado, tus pruebas necesitarán una base de datos para interactuar también. Para escribir pruebas eficientes, necesitarás entender cómo configurar esta base de datos y poblarla con datos de ejemplo.</p><p>Por defecto, cada aplicación Rails tiene tres entornos: desarrollo, prueba y producción. La base de datos para cada uno de ellos se configura en <code>config/database.yml</code>.</p><p>Una base de datos de prueba dedicada te permite configurar e interactuar con datos de prueba de forma aislada. De esta manera, tus pruebas pueden manipular los datos de prueba con confianza, sin preocuparse por los datos en las bases de datos de desarrollo o producción.</p><h3 id="manteniendo-el-esquema-de-la-base-de-datos-de-prueba"><a class="anchorlink" href="#manteniendo-el-esquema-de-la-base-de-datos-de-prueba"><span>4.1</span> Manteniendo el Esquema de la Base de Datos de Prueba</a></h3><p>Para ejecutar tus pruebas, tu base de datos de prueba necesitará tener la estructura actual. El ayudante de prueba verifica si tu base de datos de prueba tiene alguna migración pendiente. Intentará cargar tu <code>db/schema.rb</code> o <code>db/structure.sql</code> en la base de datos de prueba. Si las migraciones aún están pendientes, se generará un error. Por lo general, esto indica que tu esquema no está completamente migrado. Ejecutar las migraciones contra la base de datos de desarrollo (<code>bin/rails db:migrate</code>) actualizará el esquema.</p><p>NOTA: Si hubo modificaciones en las migraciones existentes, la base de datos de prueba necesita ser reconstruida. Esto se puede hacer ejecutando <code>bin/rails db:test:prepare</code>.</p><h3 id="lo-básico-sobre-los-fixtures"><a class="anchorlink" href="#lo-básico-sobre-los-fixtures"><span>4.2</span> Lo Básico sobre los Fixtures</a></h3><p>Para buenas pruebas, necesitarás pensar en cómo configurar los datos de prueba. En Rails, puedes manejar esto definiendo y personalizando fixtures. Puedes encontrar documentación completa en la <a href="https://edgeapi.rubyonrails.org/classes/ActiveRecord/FixtureSet.html">documentación de la API de Fixtures</a>.</p><h4 id="¿qué-son-los-fixtures-questionmark"><a class="anchorlink" href="#¿qué-son-los-fixtures-questionmark"><span>4.2.1</span> ¿Qué son los Fixtures?</a></h4><p><em>Fixtures</em> es una palabra elegante para datos de ejemplo. Los fixtures te permiten poblar tu base de datos de prueba con datos predefinidos antes de que se ejecuten tus pruebas. Los fixtures son independientes de la base de datos y están escritos en YAML. Hay un archivo por modelo.</p><p>NOTA: Los fixtures no están diseñados para crear cada objeto que tus pruebas necesiten, y se manejan mejor cuando solo se usan para datos predeterminados que se pueden aplicar al caso común.</p><p>Encontrarás fixtures bajo tu directorio <code>test/fixtures</code>. Cuando ejecutas <code>bin/rails generate model</code> para crear un nuevo modelo, Rails crea automáticamente plantillas de fixtures en este directorio.</p><h4 id="yaml"><a class="anchorlink" href="#yaml"><span>4.2.2</span> YAML</a></h4><p>Los fixtures formateados en YAML son una forma amigable para describir tus datos de ejemplo. Estos tipos de fixtures tienen la extensión de archivo <strong>.yml</strong> (como en <code>users.yml</code>).</p><p>Aquí hay un archivo de fixture YAML de ejemplo:</p><div class="interstitial code">
<pre><code class="highlight yaml"><span class="c1"># ¡mira y asómbrate! ¡Soy un comentario YAML!</span>
<span class="na">david</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">David Heinemeier Hansson</span>
<span class="na">birthday</span><span class="pi">:</span> <span class="s">1979-10-15</span>
<span class="na">profession</span><span class="pi">:</span> <span class="s">Systems development</span>
<span class="na">steve</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">Steve Ross Kellock</span>
<span class="na">birthday</span><span class="pi">:</span> <span class="s">1974-09-27</span>
<span class="na">profession</span><span class="pi">:</span> <span class="s">guy with keyboard</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="# ¡mira y asómbrate! ¡Soy un comentario YAML!
david:
name: David Heinemeier Hansson
birthday: 1979-10-15
profession: Systems development
steve:
name: Steve Ross Kellock
birthday: 1974-09-27
profession: guy with keyboard
">Copy</button>
</div>
<p>Cada fixture se le da un nombre seguido de una lista indentada de pares clave/valor separados por dos puntos. Los registros se separan típicamente por una línea en blanco. Puedes colocar comentarios en un archivo de fixture usando el carácter # en la primera columna.</p><p>Si estás trabajando con <a href="/association_basics.html">asociaciones</a>, puedes definir un nodo de referencia entre dos fixtures diferentes. Aquí tienes un ejemplo con una asociación <code>belongs_to</code>/<code>has_many</code>:</p><div class="interstitial code">
<pre><code class="highlight yaml"><span class="c1"># test/fixtures/categories.yml</span>
<span class="na">about</span><span class="pi">:</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">About</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="about:
name: About
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight yaml"><span class="c1"># test/fixtures/articles.yml</span>
<span class="na">first</span><span class="pi">:</span>
<span class="na">title</span><span class="pi">:</span> <span class="s">Welcome to Rails!</span>
<span class="na">category</span><span class="pi">:</span> <span class="s">about</span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="first:
title: Welcome to Rails!
category: about
">Copy</button>
</div>
<div class="interstitial code">
<pre><code class="highlight yaml"><span class="c1"># test/fixtures/action_text/rich_texts.yml</span>
<span class="na">first_content</span><span class="pi">:</span>
<span class="na">record</span><span class="pi">:</span> <span class="s">first (Article)</span>
<span class="na">name</span><span class="pi">:</span> <span class="s">content</span>
<span class="na">body</span><span class="pi">:</span> <span class="s"><div>Hello, from <strong>a fixture</strong></div></span>
</code></pre>
<button class="clipboard-button" data-clipboard-text="first_content:
record: first (Article)
name: content
body: <div>Hello, from <strong>a fixture</strong></div>
">Copy</button>