{"id":230120,"date":"2022-11-28T16:05:00","date_gmt":"2022-11-28T13:05:00","guid":{"rendered":"https:\/\/wordpress.mediadoma.com\/?p=230120"},"modified":"2022-11-09T20:10:55","modified_gmt":"2022-11-09T17:10:55","slug":"una-introduccion-a-la-reflexion-en-php-y-como-juega-en-las-pruebas-unitarias","status":"publish","type":"post","link":"https:\/\/wordpress.mediadoma.com\/es\/una-introduccion-a-la-reflexion-en-php-y-como-juega-en-las-pruebas-unitarias\/","title":{"rendered":"Una introducci\u00f3n a la reflexi\u00f3n en PHP (y c\u00f3mo juega en las pruebas unitarias)"},"content":{"rendered":"\n<p>Durante las \u00faltimas semanas, he estado escribiendo sobre <strong><a href=\"https:\/\/tommcfarlin.com\/tag\/unit-testing\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">pruebas unitarias<\/a><\/strong> para los <strong><a href=\"https:\/\/tommcfarlin.com\/registration-info\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">miembros<\/a><\/strong> del sitio (y algo que planeo seguir haciendo en la pr\u00f3xima publicaci\u00f3n). Es algo que pienso; si escribe c\u00f3digo del lado del servidor, deber\u00eda hacerlo.<\/p>\n<p>Por supuesto, es m\u00e1s f\u00e1cil para m\u00ed decirlo que hacerlo, as\u00ed que aunque trato de asegurarme de hacer un buen trabajo, siempre hay margen para mejorar. Digo eso m\u00e1s como un control personal que cualquier otra cosa, as\u00ed que estoy divagando.<\/p>\n<p>Uno de los conceptos que a menudo surgen durante las pruebas es la idea de probar los valores de los atributos privados. Por ejemplo, supongamos que tiene un setter, pero no necesariamente tiene un getter para ese valor en particular.<\/p>\n<p>Es f\u00e1cil decir &quot;Bueno, entonces necesitas escribir un captador&quot;, pero no siempre es as\u00ed. Quiero decir, \u00bfqu\u00e9 pasa si est\u00e1s almacenando informaci\u00f3n dentro de la clase que no necesita estar expuesta a clases de terceros?<\/p>\n<p>Entonces, \u00bfc\u00f3mo se supone que debemos escribir pruebas contra ese tipo de datos cuando queremos acceder a ellos pero no tenemos la capacidad de hacerlo y no queremos comprometer la integridad de nuestro trabajo?<\/p>\n<p>Ah\u00ed es donde entra en juego la reflexi\u00f3n.<\/p>\n<h2>Reflexi\u00f3n en PHP<\/h2>\n<p>Espec\u00edficamente, para comprender c\u00f3mo inspeccionar el valor de una variable dada desde afuera hacia adentro, debe saber c\u00f3mo usar la reflexi\u00f3n.<\/p>\n<p>Afortunadamente, PHP nos brinda una poderosa API para hacer eso, y probablemente valga la pena profundizar en los detalles de eso en otra publicaci\u00f3n. Pero, para este, me quedo con lo b\u00e1sico.<\/p>\n<h3>Una definici\u00f3n de trabajo<\/h3>\n<p>Primero, un vistazo a lo que significa reflexi\u00f3n. El manual de PHP <strong><a href=\"https:\/\/php.net\/manual\/en\/class.reflectionclass.php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">lo define como<\/a><\/strong> :<\/p>\n<blockquote>\n<p>La clase <strong>ReflectionClass<\/strong> informa sobre una clase.<\/p>\n<\/blockquote>\n<p>Pero creo que vale la pena tener algo un poco m\u00e1s s\u00f3lido. Vamos con algo as\u00ed al menos para este post:<\/p>\n<blockquote>\n<p>La reflexi\u00f3n es c\u00f3mo un programa se inspecciona a s\u00ed mismo y se modifica a s\u00ed mismo durante el tiempo de ejecuci\u00f3n.<\/p>\n<\/blockquote>\n<p>Tal vez no sea genial; tal vez no.<\/p>\n<p><a href=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-164036-61e75c7d26d26.png\" data-rel=\"lightbox\"><img decoding=\"async\" class=\"SDStudio-light-box-enable SDStudio-editor-tools-md-imp\" src=\"https:\/\/wordpress.mediadoma.com\/wp-content\/uploads\/2022\/01\/post-164036-61e75c7d26d26.png\" alt=\"Una introducci\u00f3n a la reflexi\u00f3n en PHP (y c\u00f3mo juega en las pruebas unitarias)\" ><\/a><\/p>\n<p>Pero servir\u00e1 para el prop\u00f3sito de esta publicaci\u00f3n.<\/p>\n<h3>Lectura de un valor a trav\u00e9s de la reflexi\u00f3n<\/h3>\n<p>Supongamos que para esta publicaci\u00f3n, tiene una clase de espacios de nombres en <strong>AcmePluginAPIClient<\/strong> y tiene una propiedad llamada nombre de <strong>usuario<\/strong>. Echaremos un vistazo a c\u00f3mo puede verse una implementaci\u00f3n muy b\u00e1sica de esto m\u00e1s adelante.<\/p>\n<p>Por supuesto, estar\u00eda mucho m\u00e1s desarrollado en un complemento real.<\/p>\n<p>Sin embargo, supongamos que desea establecer el valor del atributo y luego leer su valor. La advertencia es que la propiedad est\u00e1 marcada como <strong>privada<\/strong> y no hay forma de leerla desde el exterior.<\/p>\n<p>Aqu\u00ed es donde la reflexi\u00f3n es \u00fatil. Es decir, podemos usar una parte del programa para mirarse a s\u00ed mismo y reportar lo que ve. (Reflexi\u00f3n, \u00bfentiendes? Es como cuando queremos saber qu\u00e9 pasa con nosotros mismos y no hay nadie m\u00e1s alrededor, as\u00ed que nos miramos en un espejo y vemos qu\u00e9 hay all\u00ed).<\/p>\n<p>Para hacer esto, necesitas hacer cinco cosas:<\/p>\n<ol>\n<li>Cree una instancia de la clase que desea probar,<\/li>\n<li>Establecer el valor de la variable,<\/li>\n<li>Tome una instancia de <strong>ReflectionClass<\/strong> para la clase que queremos probar,<\/li>\n<li>Establezca su propiedad en accesible,<\/li>\n<li>Leer el valor.<\/li>\n<\/ol>\n<p>As\u00ed que aqu\u00ed hay una serie de puntos esenciales que le proporcionar\u00e1n los pasos necesarios para hacer exactamente eso.<\/p>\n<h4>1 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/c835d263062e768980d5ad3f6941f60e#file-00-apiclient-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Instanciar la clase<\/a><\/h4>\n<pre><code>&lt;?php\n\nnamespace AcmePlugin;\n\nclass APIClient\n{\n  private $username;\n\n  \/\/ Other functions for class implementation...\n}\n<\/code><\/pre>\n<h4>2 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/c835d263062e768980d5ad3f6941f60e#file-01-setusername-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Establecer el valor<\/a><\/h4>\n<pre><code>&lt;?php\n\nnamespace AcmePlugin;\n\nclass APIClient\n{\n  private $username;\n\n  public function setUsername($username)\n  {\n    $this-&gt;username = $username;\n  }\n\n  \/\/ Other functions for class implementation...\n}\n<\/code><\/pre>\n<h4>3 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/c835d263062e768980d5ad3f6941f60e#file-01-apiclienttest-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Crear instancias de objetos reflejados<\/a><\/h4>\n<pre><code>&lt;?php\n\nnamespace AcmePluginTests;\n\nuse AcmePluginAPIAPIClient;\n\nclass APIClientTest\n{\n  public function setUsername()\n  {\n\n    \/\/ Instantiate the class.\n    $client = new APIClient();\n    $username = 'tommcfarlin';\n    $client-&gt;setUsername($username);\n\n    \/\/ Now get a reflected instance of the class.\n    $reflectedClient = new ReflectionClass('AcmePluginAPIAPIClient');\n\n    \/\/ More to come...\n  }\n}\n<\/code><\/pre>\n<h4>4. <a href=\"https:\/\/gist.github.com\/tommcfarlin\/c835d263062e768980d5ad3f6941f60e#file-02-setaccessibleproperty-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Configure la propiedad, m\u00e1rquela como accesible<\/a><\/h4>\n<pre><code>&lt;?php\n\nnamespace AcmePluginTests;\n\nuse AcmePluginAPIAPIClient;\n\nclass APIClientTest\n{\n  public function setUsername()\n  {\n\n    \/\/ Instantiate the class.\n    $client = new APIClient();\n    $username = 'tommcfarlin';\n    $client-&gt;setUsername($username);\n\n    \/\/ Now get a reflected instance of the class.\n    $reflectedClient = new ReflectionClass('AcmePluginAPIAPIClient');\n    $usernameProperty = new ReflectionObject($client);\n    $usernameProperty-&gt;setAccessible(true);\n\n    \/\/ More to come...\n  }\n}\n<\/code><\/pre>\n<h4>5 <a href=\"https:\/\/gist.github.com\/tommcfarlin\/c835d263062e768980d5ad3f6941f60e#file-03-readpropertyvalue-php\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">Leer el valor<\/a><\/h4>\n<pre><code>&lt;?php\n\nnamespace AcmePluginTests;\n\nuse AcmePluginAPIAPIClient;\n\nclass APIClientTest\n{\n  public function setUsername()\n  {\n\n    \/\/ Instantiate the class.\n    $client = new APIClient();\n    $username = 'tommcfarlin';\n    $client-&gt;setUsername($username);\n\n    \/\/ Now get a reflected instance of the class.\n    $reflectedClient = new ReflectionClass('AcmePluginAPIAPIClient');\n\n    \/\/ Grab a reference to the private property by making it accessible.\n    $usernameProperty = new ReflectionObject($client);\n    $usernameProperty-&gt;setAccessible(true);\n\n    \/\/ And finally, read it's value.\n    $usernameValue = $usernameProperty-&gt;getValue($client);\n  }\n}\n<\/code><\/pre>\n<h2>Y ese es el manual b\u00e1sico sobre la reflexi\u00f3n<\/h2>\n<p>En este punto, esto deber\u00eda brindarle informaci\u00f3n b\u00e1sica sobre qu\u00e9 es Reflection, c\u00f3mo usarlo y por qu\u00e9 es \u00fatil, especialmente en el caso de <strong><a href=\"https:\/\/tommcfarlin.com\/tag\/unit-testing\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">las pruebas unitarias<\/a><\/strong>.<\/p>\n<p>Este es uno de esos conceptos que pueden volverse m\u00e1s complejos porque la API de reflexi\u00f3n de PHP es bastante poderosa (pero relativamente f\u00e1cil de entender). Sin embargo, cuando lo combina con pruebas unitarias, hay muchas cosas que se pueden hacer.<\/p>\n<h3>mi enchufe desvergonzado<\/h3>\n<p>Dicho esto, si est\u00e1 interesado en conocer los entresijos de este tipo de cosas, no dude en consultar el \u00e1rea <strong><a href=\"https:\/\/tommcfarlin.com\/registration-info\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">exclusiva para miembros<\/a><\/strong> del sitio. Estoy creando, cada semana, <strong><a href=\"https:\/\/tommcfarlin.com\/members-only-content\/\" target=\"_blank\" rel=\"noopener nofollow\" class=\"external external_icon\">una acumulaci\u00f3n de cosas<\/a><\/strong> para ayudarnos a enfocarnos en adoptar mejores pr\u00e1cticas como desarrolladores de WordPress.<\/p>\n<p>Unit Testing, Reflection y m\u00e1s es solo la \u00faltima parte.<\/p>\n<p><div id=\"PostUnique_PostSource\" style=\"padding-top: 50px\">Fuente de grabaci\u00f3n:  <a target=\"_blank\" rel=\"noopener nofollow\" href=\"\/\/tommcfarlin.com\" class=\"external external_icon\">tommcfarlin.com<\/a><\/div><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Comprender los conceptos b\u00e1sicos de la reflexi\u00f3n en PHP puede ayudar a que su programaci\u00f3n, especialmente las pruebas, sea mucho m\u00e1s f\u00e1cil.<\/p>\n","protected":false},"author":1,"featured_media":164037,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_wp_rev_ctl_limit":""},"categories":[892,716,800],"tags":[1172],"class_list":["post-230120","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-codigo","category-desarrollador","category-php-2","tag-affiai-es"],"_links":{"self":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230120","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/comments?post=230120"}],"version-history":[{"count":0,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/posts\/230120\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media\/164037"}],"wp:attachment":[{"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/media?parent=230120"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/categories?post=230120"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/wordpress.mediadoma.com\/es\/wp-json\/wp\/v2\/tags?post=230120"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}