{"id":913,"date":"2011-01-15T21:07:36","date_gmt":"2011-01-16T00:07:36","guid":{"rendered":"https:\/\/devkico.itexto.com.br\/?p=913"},"modified":"2011-11-03T11:53:09","modified_gmt":"2011-11-03T14:53:09","slug":"grails-testando-sua-aplicacao","status":"publish","type":"post","link":"https:\/\/devkico.itexto.com.br\/?p=913","title":{"rendered":"Grails: testando sua aplica\u00e7\u00e3o"},"content":{"rendered":"<p><a href=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b.jpeg\"><img loading=\"lazy\" decoding=\"async\" class=\"alignright size-medium wp-image-914\" title=\"monstro-serie-b\" src=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg\" alt=\"\" width=\"300\" height=\"210\" srcset=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg 300w, https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b.jpeg 450w\" sizes=\"(max-width: 300px) 100vw, 300px\" \/><\/a><a href=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2010\/02\/grails_logo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignleft size-full wp-image-604\" title=\"grails_logo\" src=\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2010\/02\/grails_logo.png\" alt=\"\" width=\"163\" height=\"43\" \/><\/a>Sabe esta aplica\u00e7\u00e3o linda que voc\u00ea est\u00e1 escrevendo em Grails usando todo o dinamismo que o framework te oferece?\u00a0 Funciona perfeitamente, e em sua cabe\u00e7a n\u00e3o aparece uma situa\u00e7\u00e3o sequer na qual algo possa dar errado, certo?<\/p>\n<p>Como voc\u00ea pode ter certeza de que esta aplica\u00e7\u00e3o est\u00e1 funcionando? S\u00f3 h\u00e1 uma maneira: testando, e da maneira certa, ou seja, com testes automatizados. N\u00e3o h\u00e1 como evitar,<strong> sua aplica\u00e7\u00e3o VAI virar um monstrinho abomin\u00e1vel se voce n\u00e3o escrever testes automatizados<\/strong>.<\/p>\n<p>Os testes automatizados s\u00e3o a sua rede de seguran\u00e7a (safety net): s\u00e3o eles que te d\u00e3o seguran\u00e7a no momento da manuten\u00e7\u00e3o.<\/p>\n<p>Neste post meu objetivo \u00e9 expor como tirar proveito do <em>Testing Framework<\/em>, que \u00e9 o framework de testes adotado pelo Grails. Por\u00e9m, antes de come\u00e7ar quero acabar com um mito cretino.<\/p>\n<h2>&#8220;Eu n\u00e3o tenho tempo para escrever testes!&#8221;<\/h2>\n<p>Papo furado! Se o programador n\u00e3o escreve testes, como pode saber que sua aplica\u00e7\u00e3o est\u00e1 DE FATO funcionando? Debugando e executando a aplica\u00e7\u00e3o manualmente. E sabe qual o grande problema com esta pr\u00e1tica? Ela consome tempo: <strong>muito mais do que a escrita e execu\u00e7\u00e3o dos testes automatizados<\/strong>. E sabe o que \u00e9 pior? Ainda \u00e9 sucet\u00edvel a erros.<\/p>\n<p>Isto sem mencionar que os testes unit\u00e1rios e de integra\u00e7\u00e3o acabam se tornando a melhor documenta\u00e7\u00e3o poss\u00edvel para o seu c\u00f3digo, pois descrevem exatamente como espera-se que este funcione.<\/p>\n<p><strong>Lido este argumento sua desculpa para ser irrespons\u00e1vel evaporou.<\/strong><\/p>\n<h2>Testes unit\u00e1rios e de integra\u00e7\u00e3o: qual a diferen\u00e7a?<\/h2>\n<p>Testes unit\u00e1rios levam em considera\u00e7\u00e3o o objeto a ser verificado isolado. N\u00e3o h\u00e1 conex\u00f5es com bancos de dados, web services ou qualquer outro tipo de componente: a classe deve ser vista como um elemento autista. Como veremos, isto tr\u00e1s algumas dificuldades que o testing framework do Grails nos ajuda a resolver de uma maneira simples usando <em>mock objects<\/em>.<\/p>\n<p>Testes de integra\u00e7\u00e3o, por sua vez, levam em considera\u00e7\u00e3o, como o pr\u00f3prio nome j\u00e1 diz, a integra\u00e7\u00e3o do objeto a ser testado com componentes externos, como por exemplo bancos de dados, web services ou outros servi\u00e7os de natureza diversa. Testes de integra\u00e7\u00e3o s\u00e3o portanto muito mais caros do ponto de vista computacional, visto que precisamos iniciar a aplica\u00e7\u00e3o para que estes possam ser executados.<\/p>\n<p>\u00c9 muito comum encontrar testes unit\u00e1rios que, na realidade, s\u00e3o de integra\u00e7\u00e3o. Os <em>mock objects<\/em> entram em cena portanto como elementos externos <em>&#8220;de mentirinha&#8221;<\/em>, que nos permitem tratar o objeto isoladamente. Veremos mais sobre este recurso neste post.<\/p>\n<h2>Criando seus testes<\/h2>\n<p>Todos os testes unit\u00e1rios se encontram no diret\u00f3rio test\/unit (ou integration) presente na raiz do seu projeto Grails. J\u00e1 reparou que toda vez que voc\u00ea cria uma classe de dom\u00ednio, controlador ou biblioteca de tags (e outros artefatos), automaticamente s\u00e3o incluidos no diret\u00f3rio test\/unit?<\/p>\n<p>H\u00e1 tr\u00eas maneiras de se criar estes testes:<\/p>\n<ol>\n<li>O Grails os cria automaticamente pra voc\u00ea<\/li>\n<li>Criando a classe de teste manualmente (nesta se\u00e7\u00e3o ficar\u00e1 claro como isto \u00e9 feito)<\/li>\n<li>Usando o comando &#8220;grails create-unit-test&#8221;<\/li>\n<\/ol>\n<p>Assim como diversos aspectos do Grails, aqui tamb\u00e9m devemos nos ater a algumas conven\u00e7\u00f5es. Toda classe de teste possui o sufixo &#8220;Tests&#8221; em seu nome. Sendo assim, os testes unit\u00e1rios para a classe de dom\u00ednio Usuario, por exemplo, ficariam em test\/unit\/UsuarioTests.groovy.<\/p>\n<p>Uma classe de teste vazia \u00e9 simples como a abaixo:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\nimport grails.test.*\r\n\r\nclass UsuarioTests extends GrailsUnitTestCase {\r\nprotected void setUp() {}\r\n\r\nprotected void tearDown() {}\r\n\r\nvoid testSomething() {}\r\n}\r\n\r\n<\/pre>\n<p>O comando &#8220;grails create-unit-test&#8221; ou &#8220;grails create-integration-test&#8221; deve receber o nome do teste unit\u00e1rio ou de integra\u00e7\u00e3o a ser gerado. Voc\u00ea n\u00e3o precisa incluir o &#8220;Tests&#8221; no final do arquivo, Grails o incluir\u00e1 para voc\u00ea.<\/p>\n<h2>Testando classes de dom\u00ednio<\/h2>\n<p>Quando lidamos com linguagens din\u00e2micas como Groovy precisamos lidar com o seguinte problema:<strong><em> como testar uma classe que cont\u00e9m m\u00e9todos e atributos que s\u00f3 ser\u00e3o injetados em tempo de execu\u00e7\u00e3o?<\/em><\/strong> Fun\u00e7\u00f5es como <em>save()<\/em>, <em>validate()<\/em> ou constraints s\u00f3 funcionam ap\u00f3s injetados pelo framework.<\/p>\n<p>Podemos escrever testes de integra\u00e7\u00e3o. O problema \u00e9 que leva tempo at\u00e9 a aplica\u00e7\u00e3o ser iniciada, o que ir\u00e1 reduzir a sua produtividade. O ideal \u00e9 podermos executar testes unit\u00e1rios, que por sua pr\u00f3pria natureza s\u00e3o ordens de magnitude mais r\u00e1pidos. A solu\u00e7\u00e3o para o problema \u00e9 <em>mockar<\/em> seus objetos usando o <em>Testing Framework<\/em> do Grails!<\/p>\n<p>(assim como o GORM \u00e9 baseado no Hibernate, o Testing Framework \u00e9 baseado no JUnit que voc\u00ea j\u00e1 conhece (ou deveria conhecer! :D))<\/p>\n<p>Para ilustrar, tenha como base esta classe de dom\u00ednio:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\nclass Usuario {\r\nString nome\r\nString login\r\n\r\nstatic constraints = {\r\nnome(nullable:false, blank:false, maxSize:128, unique:true)\r\nlogin(nullable:false, blank:false, maxSize:16, unique:true)\r\n}\r\n}\r\n\r\n<\/pre>\n<p>Nosso teste unit\u00e1rio encontra-se na classe abaixo:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\nimport grails.test.*\r\n\r\nclass UsuarioTests\u00a0 extends GrailsUnitTestCase {\r\nprotected void setUp() {super.setUp()}\r\n\r\nprotected void tearDown() {super.tearDown()}\r\n\r\nvoid testConstraints() {\r\nmockDomain Usuario\r\ndef usuario = new Usuario()\r\nassertFalse usuario.validate()\r\ndef usuario_ok = new Usuario(nome:&quot;Joselino&quot;, login: &quot;joca&quot;)\r\nassertTrue usuario_ok.validate()\r\n}\r\n\r\nvoid testUnicidade() {\r\nmockDomain Usuario, &#x5B;]\r\ndef usuario1 = new Usuario(nome: &quot;Joselino&quot;, login: &quot;jose&quot;)\r\nusuario1.save()\r\ndef usuario2 = new Usuario(nome:&quot;Joselino&quot;, login:&quot;joca&quot;)\r\nassertFalse usuario2.validate() \/\/ j\u00e1 existe um Joselino!\r\n\r\n}\r\n\r\n}\r\n\r\n<\/pre>\n<p>Repare que interessante: mesmo se tratando de um teste unit\u00e1rio estou testando m\u00e9todos que s\u00f3 existem em tempo de execu\u00e7\u00e3o: no caso, o validate. Para isto, uso o m\u00e9todo mockDomain, herdado de GrailsUnitTestCase. Este injeta na classe dom\u00ednio todos os m\u00e9todos que uma classe de respeito deste tipo deve ter, como por exemplo os m\u00e9todos de valida\u00e7\u00e3o, save(), delete(), etc.<\/p>\n<p>Assim \u00e9 poss\u00edvel testar f\u00e1cilmente a valida\u00e7\u00e3o. Mais interessante ainda \u00e9 o segundo teste: testUnicidade. Repare que passo para o m\u00e9todo mockDomain uma lista vazia. Quando evoco o m\u00e9todo save(), este objeto \u00e9 na realidade armazenado naquela lista que passei como par\u00e2metro, simulando assim um banco de dados! N\u00e3o \u00e9 legal? Assim posso verificar se a constraint unique est\u00e1 de fato funcionando ou n\u00e3o.<\/p>\n<p>No caso de testes de integra\u00e7\u00e3o, \u00f3bviamente voc\u00ea n\u00e3o precisa do m\u00e9todo mockDomain, pois as classes j\u00e1 est\u00e3o prontas.<\/p>\n<h2>Testes unit\u00e1rios para controladores<\/h2>\n<p>\u00c9 muito comum encontrarmos projetos nos quais apenas classes de dom\u00ednio s\u00e3o testadas. Ap\u00f3s ler esta se\u00e7\u00e3o, sua desculpa para n\u00e3o testar seus controladores acabou! :D<\/p>\n<p>Para testar suas classes, voc\u00ea deve criar um teste tal como faria normalmente. A diferen\u00e7a \u00e9 que este teste n\u00e3o extender\u00e1 a classe GrailsUnitTestCase, mas sim ControllerUnitTestCase. Nosso controlador de exemplo segue abaixo. Observe que ele s\u00f3 tem uma action.<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\n\r\nclass BoboController {\r\n\r\ndef bobo = {\r\n\r\nif (! params.valor) {\r\nredirect(action:&quot;outra&quot;, controller:&quot;outro&quot;)\r\n                return\r\n}\r\nswitch (params.valor) {\r\ncase &quot;boo&quot;:\r\nrender &quot;N\u00e3o sou bobo n\u00e3o&quot;\r\nbreak\r\ncase &quot;bonito&quot;\r\nreturn &#x5B;resposta:&quot;sou lindo mesmo!&quot;]\r\ncase &quot;nada&quot;\r\nthrow new Exception(&quot;Nada???&quot;)\r\n}\r\n}\r\n\r\n}\r\n\r\n<\/pre>\n<p>Escrevi alguns testes para esta classe que ilustra bem o que podemos fazer com este framework:<\/p>\n<pre class=\"brush: java; title: ; notranslate\" title=\"\">\r\nimport grails.test.*\r\n\r\nclass BoboControllerTests extends ControllerUnitTestCase {\r\n    protected void setUp() {\r\n        super.setUp()\r\n    }\r\n\r\n    protected void tearDown() {\r\n        super.tearDown()\r\n    }\r\n\r\n    void testRedirect() {\r\n\t\tcontroller.bobo()\r\n\t\tassertEquals &quot;outra&quot;, redirectArgs.action\r\n\t\tassertEquals &quot;outro&quot;, redirectArgs.controller\r\n    }\r\n\r\n\tvoid testRender() {\r\n\t\tmockParams.valor = &quot;bobo&quot;\r\n\t\tcontroller.bobo()\r\n\t\tassertEquals mockResponse.contentAsString, &quot;N\u00e3o sou bobo n\u00e3o&quot;\r\n\t}\r\n\r\n\tvoid testModel() {\r\n\t\tmockParams.valor = &quot;bonito&quot;\r\n\t\tdef model = controller.bobo()\r\n\t\tassertEquals model.resposta, &quot;sou lindo mesmo!&quot;\r\n\t}\r\n\r\n}\r\n<\/pre>\n<p>Nosso primeiro teste \u00e9 o de redirecionamento. Observe o m\u00e9todo testRedirect(). A classe ControllerUnitTestCase possui um atributo chamado chamado <em>controller<\/em>, que simula o nosso controlador (o controlador \u00e9 identificado por default pelo nome que demos \u00e0 classe do nosso teste).\u00a0 Chamando nossa action sem nenhum parametro, esperamos, pelo c\u00f3digo que expus acima, que sejamos redirecionados para a action &#8220;outra&#8221; do controller &#8220;outro&#8221;.<\/p>\n<p>Entra em cena ent\u00e3o outro atributo de nossa classe: <em>redirectArgs<\/em>. Ele normalmente possui 3 par\u00e2metros: controller, action e model. Assim podemos ver se o nosso controlador est\u00e1 se comportando como esperavamos inicialmente.<\/p>\n<p>Se quisermos testar o funcionamento de nosso controlador passando-lhe par\u00e2metros, usamos o atributo <em>mockParams<\/em>, que funciona exatamente como o params que estamos acostumados a trabalhar. Primeiro devemos incluir os valores neste atributo e em seguida executar nossa action para ver o resultado. Em <em>testeRender<\/em> podemos ver um exemplo de como verificar se o texto renderizado pelo nosso controlador foi o que esper\u00e1vamos receber. Para isto, usamos o atributo mockResponse.<\/p>\n<p>Finalmente, inclui tamb\u00e9m um teste para o valor de retorno de nosso controlador. Observe o m\u00e9todo <em>testModel<\/em>. Basta executar nossa action como se fosse uma fun\u00e7\u00e3o convencional. O restante do c\u00f3digo \u00e9 similar ao que escreveriamos usando um teste unit\u00e1rio convencional.<\/p>\n<p>H\u00e1 mais alguns atributos que merecem ser mencionados: s\u00e3o estes:<\/p>\n<ul>\n<li>mockRequest: usado para simular uma inst\u00e2ncia de HttpServletRequest<\/li>\n<li>mockSession: usado para simular uma sess\u00e3o (voc\u00ea pode, por exemplo, verificar se seu controller alterou ou n\u00e3o sua sess\u00e3o ap\u00f3s a execu\u00e7\u00e3o de uma action, o que \u00e9 MUITO \u00fatil)<\/li>\n<li>mockFlash: usado para simular o contexto flash. Muito \u00fatil para verificar mensagens de alerta que precisam ser enviadas ao usu\u00e1rio, por exemplo.<\/li>\n<\/ul>\n<h2>Executando os testes<\/h2>\n<p>Com sua aplica\u00e7\u00e3o funcionando, o pr\u00f3ximo passo \u00e9 executar seus testes. Para isto, voc\u00ea usa o comando &#8220;grails test-app&#8221;, que ir\u00e1 primeiro executar todos os seus testes.<\/p>\n<p>Caso queira executar apenas alguns testes, basta passar como par\u00e2metro os nomes dos testes excluindo o sufixo &#8220;Tests&#8221;, como por exemplo<\/p>\n<p>grails test-app BoboController<\/p>\n<p>Para executar apenas testes unit\u00e1rios, execute<\/p>\n<p>grails test-app unit<\/p>\n<p>e para executar apenas os testes de integra\u00e7\u00e3o, execute<\/p>\n<p>grails test-app integration<\/p>\n<p>Executados os seus testes, ser\u00e1 criado o diret\u00f3rio target\/test-reports em seu projeto, contendo o relat\u00f3rio de execu\u00e7\u00e3o dos seus testes. Caso esteja usando Grails 1.1, estes relat\u00f3rios ir\u00e3o estar em test\/test-reports.<\/p>\n<h2>Concluindo<\/h2>\n<p>Um programador que n\u00e3o escreve testes automatizados \u00e9 como um cirurgi\u00e3o que n\u00e3o lava as m\u00e3os antes de uma cirurgia (n\u00e3o me lembro aonde li isto). Com Grails, a escrita dos testes, como pode ser visto, \u00e9 um processo simples e direto, que ir\u00e1 lhe garantir noites de sono tranquilas ap\u00f3s ter entregue seus sistemas.<\/p>\n<p>Agora, se mesmo assim voc\u00ea ainda n\u00e3o quer escrever seus testes, bem: sinto muito, voc\u00ea deve procurar outro ramo se quiser manter um n\u00edvel m\u00ednimo de sa\u00fade. :D<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Sabe esta aplica\u00e7\u00e3o linda que voc\u00ea est\u00e1 escrevendo em Grails usando todo o dinamismo que o framework te oferece?\u00a0 Funciona perfeitamente, e em sua cabe\u00e7a n\u00e3o aparece uma situa\u00e7\u00e3o sequer na qual algo possa dar errado, certo? Como voc\u00ea pode ter certeza de que esta aplica\u00e7\u00e3o est\u00e1 funcionando? S\u00f3 h\u00e1 uma maneira: testando, e da [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_coblocks_attr":"","_coblocks_dimensions":"","_coblocks_responsive_height":"","_coblocks_accordion_ie_support":"","site-sidebar-layout":"default","site-content-layout":"","ast-site-content-layout":"","site-content-style":"default","site-sidebar-style":"default","ast-global-header-display":"","ast-banner-title-visibility":"","ast-main-header-display":"","ast-hfb-above-header-display":"","ast-hfb-below-header-display":"","ast-hfb-mobile-header-display":"","site-post-title":"","ast-breadcrumbs-content":"","ast-featured-img":"","footer-sml-layout":"","theme-transparent-header-meta":"","adv-header-id-meta":"","stick-header-meta":"","header-above-stick-meta":"","header-main-stick-meta":"","header-below-stick-meta":"","astra-migrate-meta-layouts":"default","ast-page-background-enabled":"default","ast-page-background-meta":{"desktop":{"background-color":"var(--ast-global-color-4)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"ast-content-background-meta":{"desktop":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"tablet":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""},"mobile":{"background-color":"var(--ast-global-color-5)","background-image":"","background-repeat":"repeat","background-position":"center center","background-size":"auto","background-attachment":"scroll","background-type":"","background-media":"","overlay-type":"","overlay-color":"","overlay-gradient":""}},"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[3,30,5],"tags":[],"class_list":["post-913","post","type-post","status-publish","format-standard","hentry","category-grails","category-grails-guia-rapido-e-indireto","category-groovy"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v22.8 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/devkico.itexto.com.br\/?p=913\" \/>\n<meta property=\"og:locale\" content=\"pt_BR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico\" \/>\n<meta property=\"og:description\" content=\"Sabe esta aplica\u00e7\u00e3o linda que voc\u00ea est\u00e1 escrevendo em Grails usando todo o dinamismo que o framework te oferece?\u00a0 Funciona perfeitamente, e em sua cabe\u00e7a n\u00e3o aparece uma situa\u00e7\u00e3o sequer na qual algo possa dar errado, certo? Como voc\u00ea pode ter certeza de que esta aplica\u00e7\u00e3o est\u00e1 funcionando? S\u00f3 h\u00e1 uma maneira: testando, e da [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/devkico.itexto.com.br\/?p=913\" \/>\n<meta property=\"og:site_name\" content=\"\/dev\/Kico\" \/>\n<meta property=\"article:published_time\" content=\"2011-01-16T00:07:36+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2011-11-03T14:53:09+00:00\" \/>\n<meta property=\"og:image\" content=\"http:\/\/www.itexto.net\/devkico\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg\" \/>\n<meta name=\"author\" content=\"Kico (Henrique Lobo Weissmann)\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@loboweissmann\" \/>\n<meta name=\"twitter:label1\" content=\"Escrito por\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kico (Henrique Lobo Weissmann)\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. tempo de leitura\" \/>\n\t<meta name=\"twitter:data2\" content=\"9 minutos\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913\",\"url\":\"https:\/\/devkico.itexto.com.br\/?p=913\",\"name\":\"Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico\",\"isPartOf\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage\"},\"image\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage\"},\"thumbnailUrl\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg\",\"datePublished\":\"2011-01-16T00:07:36+00:00\",\"dateModified\":\"2011-11-03T14:53:09+00:00\",\"author\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7\"},\"breadcrumb\":{\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913#breadcrumb\"},\"inLanguage\":\"pt-BR\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/devkico.itexto.com.br\/?p=913\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage\",\"url\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg\",\"contentUrl\":\"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/devkico.itexto.com.br\/?p=913#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/devkico.itexto.com.br\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Grails: testando sua aplica\u00e7\u00e3o\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#website\",\"url\":\"https:\/\/devkico.itexto.com.br\/\",\"name\":\"\/dev\/Kico\",\"description\":\"Desenvolvendo software\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/devkico.itexto.com.br\/?s={search_term_string}\"},\"query-input\":\"required name=search_term_string\"}],\"inLanguage\":\"pt-BR\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7\",\"name\":\"Kico (Henrique Lobo Weissmann)\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"pt-BR\",\"@id\":\"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g\",\"caption\":\"Kico (Henrique Lobo Weissmann)\"},\"sameAs\":[\"https:\/\/x.com\/loboweissmann\"],\"url\":\"https:\/\/devkico.itexto.com.br\/?author=1\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/devkico.itexto.com.br\/?p=913","og_locale":"pt_BR","og_type":"article","og_title":"Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico","og_description":"Sabe esta aplica\u00e7\u00e3o linda que voc\u00ea est\u00e1 escrevendo em Grails usando todo o dinamismo que o framework te oferece?\u00a0 Funciona perfeitamente, e em sua cabe\u00e7a n\u00e3o aparece uma situa\u00e7\u00e3o sequer na qual algo possa dar errado, certo? Como voc\u00ea pode ter certeza de que esta aplica\u00e7\u00e3o est\u00e1 funcionando? S\u00f3 h\u00e1 uma maneira: testando, e da [&hellip;]","og_url":"https:\/\/devkico.itexto.com.br\/?p=913","og_site_name":"\/dev\/Kico","article_published_time":"2011-01-16T00:07:36+00:00","article_modified_time":"2011-11-03T14:53:09+00:00","og_image":[{"url":"http:\/\/www.itexto.net\/devkico\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg"}],"author":"Kico (Henrique Lobo Weissmann)","twitter_card":"summary_large_image","twitter_creator":"@loboweissmann","twitter_misc":{"Escrito por":"Kico (Henrique Lobo Weissmann)","Est. tempo de leitura":"9 minutos"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/devkico.itexto.com.br\/?p=913","url":"https:\/\/devkico.itexto.com.br\/?p=913","name":"Grails: testando sua aplica\u00e7\u00e3o - \/dev\/Kico","isPartOf":{"@id":"https:\/\/devkico.itexto.com.br\/#website"},"primaryImageOfPage":{"@id":"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage"},"image":{"@id":"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage"},"thumbnailUrl":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg","datePublished":"2011-01-16T00:07:36+00:00","dateModified":"2011-11-03T14:53:09+00:00","author":{"@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7"},"breadcrumb":{"@id":"https:\/\/devkico.itexto.com.br\/?p=913#breadcrumb"},"inLanguage":"pt-BR","potentialAction":[{"@type":"ReadAction","target":["https:\/\/devkico.itexto.com.br\/?p=913"]}]},{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/devkico.itexto.com.br\/?p=913#primaryimage","url":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg","contentUrl":"https:\/\/devkico.itexto.com.br\/wp-content\/uploads\/2011\/01\/monstro-serie-b-300x210.jpg"},{"@type":"BreadcrumbList","@id":"https:\/\/devkico.itexto.com.br\/?p=913#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/devkico.itexto.com.br\/"},{"@type":"ListItem","position":2,"name":"Grails: testando sua aplica\u00e7\u00e3o"}]},{"@type":"WebSite","@id":"https:\/\/devkico.itexto.com.br\/#website","url":"https:\/\/devkico.itexto.com.br\/","name":"\/dev\/Kico","description":"Desenvolvendo software","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/devkico.itexto.com.br\/?s={search_term_string}"},"query-input":"required name=search_term_string"}],"inLanguage":"pt-BR"},{"@type":"Person","@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/502ab8892631bb005d6da2269fe5a3a7","name":"Kico (Henrique Lobo Weissmann)","image":{"@type":"ImageObject","inLanguage":"pt-BR","@id":"https:\/\/devkico.itexto.com.br\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/dd6973d86a689bc63122b2e603f25be3?s=96&d=mm&r=g","caption":"Kico (Henrique Lobo Weissmann)"},"sameAs":["https:\/\/x.com\/loboweissmann"],"url":"https:\/\/devkico.itexto.com.br\/?author=1"}]}},"jetpack_featured_media_url":"","jetpack-related-posts":[],"jetpack_sharing_enabled":true,"jetpack_likes_enabled":true,"_links":{"self":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/913"}],"collection":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=913"}],"version-history":[{"count":7,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/913\/revisions"}],"predecessor-version":[{"id":1012,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=\/wp\/v2\/posts\/913\/revisions\/1012"}],"wp:attachment":[{"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=913"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=913"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devkico.itexto.com.br\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=913"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}