Tutorial de PyTest:Qué es, Cómo instalar, Framework, Aserciones
¿Qué es PyTest?
PyTest es un marco de prueba que permite a los usuarios escribir códigos de prueba utilizando el lenguaje de programación Python. Le ayuda a escribir casos de prueba simples y escalables para bases de datos, API o UI. PyTest se utiliza principalmente para escribir pruebas para API. Ayuda a escribir pruebas desde pruebas unitarias simples hasta pruebas funcionales complejas.
¿Por qué usar PyTest?
Algunas de las ventajas de pytest son
- Muy fácil para empezar debido a su sintaxis simple y fácil.
- Puede ejecutar pruebas en paralelo.
- Puede ejecutar una prueba específica o un subconjunto de pruebas
- Detectar pruebas automáticamente
- Omitir pruebas
- Código abierto
En este tutorial de Python PyTest, aprenderá:
- ¿Qué es PyTest?
- ¿Por qué usar PyTest?
- Cómo instalar PyTest
- Primera PyTest básica
- Afirmaciones en PyTest
- Cómo identifica PyTest los archivos de prueba y los métodos de prueba
- Ejecute varias pruebas desde un archivo específico y varios archivos
- Ejecute un subconjunto de la prueba completa con PyTest
- Ejecutar pruebas en paralelo con Pytest
- Accesorios Pytest
- Prueba parametrizada de Pytest
- Pytest Xfail/Omitir pruebas
- XML de resultados
- Pytest Framework probando una API
Cómo instalar PyTest
El siguiente es un proceso sobre cómo instalar PyTest:
Paso 1) Puede instalar pytest por
pip install pytest==2.9.1
Una vez completada la instalación, puede confirmarla con por
py.test -h
Esto mostrará la ayuda
Primer PyTest básico
Ahora, aprenderemos a usar Pytest con un ejemplo básico de PyTest.
Cree una carpeta study_pytest. Vamos a crear nuestros archivos de prueba dentro de esta carpeta.
Navegue a esa carpeta en su línea de comando.
Cree un archivo llamado test_sample1.py dentro de la carpeta
Agregue el siguiente código y guárdelo
import pytest def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed" def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
Ejecute la prueba usando el comando
py.test
Obtendrá resultados como
test_sample1.py F. ============================================== FAILURES ======================================== ____________________________________________ test_sample1 ______________________________________ def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed" E AssertionError: test failed E assert 5 == 6 test_sample1.py:6: AssertionError
Aquí en test_sample1.py F.
F dice fracaso
Punto(.) dice éxito.
En la sección de fallas, puede ver los métodos fallidos y la línea de falla. Aquí x==y significa 5==6 que es falso.
A continuación, en este tutorial de PyTest, aprenderemos sobre la aserción en PyTest.
Afirmaciones en PyTest
Las aserciones de Pytest son comprobaciones que devuelven el estado Verdadero o Falso. En Python Pytest, si una aserción falla en un método de prueba, entonces la ejecución del método se detiene allí. El código restante en ese método de prueba no se ejecuta y las afirmaciones de Pytest continuarán con el siguiente método de prueba.
Ejemplos de afirmaciones de Pytest:
assert "hello" == "Hai" is an assertion failure. assert 4==4 is a successful assertion assert True is a successful assertion assert False is an assertion failure.
Considere
assert x == y,"test failed because x=" + str(x) + " y=" + str(y)
Coloque este código en test_file1_method1() en lugar de la afirmación
assert x == y,"test failed"
Ejecutar la prueba arrojará el error como AssertionError:prueba fallida x=5 y=6
Cómo identifica PyTest los archivos de prueba y los métodos de prueba
Por defecto, pytest solo identifica los nombres de archivo que comienzan con test_ o terminando en _test como los archivos de prueba. Sin embargo, podemos mencionar explícitamente otros nombres de archivo (explicado más adelante). Pytest requiere que los nombres de los métodos de prueba comiencen con “test .” Todos los demás nombres de métodos serán ignorados incluso si solicitamos explícitamente ejecutar esos métodos.
Vea algunos ejemplos de nombres de archivo pytest válidos y no válidos
test_login.py - valid login_test.py - valid testlogin.py -invalid logintest.py -invalid
Nota:Sí, podemos pedirle explícitamente a pytest que elija testlogin.py y logintest.py
Vea algunos ejemplos de métodos de prueba de pytest válidos e inválidos
def test_file1_method1(): - valid def testfile1_method1(): - valid def file1_method1(): - invalid
Nota:Incluso si mencionamos explícitamente file1_method1(), pytest no ejecutará este método.
Ejecute varias pruebas desde un archivo específico y varios archivos
Actualmente, dentro de la carpeta study_pytest, tenemos un archivo test_sample1.py. Supongamos que tenemos varios archivos, digamos test_sample2.py, test_sample3.py. Para ejecutar todas las pruebas de todos los archivos en la carpeta y subcarpetas, solo necesitamos ejecutar el comando pytest.
py.test
Esto ejecutará todos los nombres de archivo que comienzan con test_ y los nombres de archivo que terminan con _test en esa carpeta y subcarpetas debajo de esa carpeta.
Para ejecutar pruebas solo desde un archivo específico, podemos usar py.test
py.test test_sample1.py
Ejecutar un subconjunto de la prueba completa con PyTest
A veces no queremos ejecutar todo el conjunto de pruebas. Pytest nos permite ejecutar pruebas específicas. Podemos hacerlo de 2 maneras
- Agrupación de nombres de pruebas por coincidencia de subcadenas
- Agrupación de pruebas por marcadores
Ya tenemos test_sample1.py. Cree un archivo test_sample2.py y agréguele el siguiente código
def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
Así que tenemos actualmente
- test_sample1.py
- test_file1_method1()
- test_file1_method2()
- test_sample2.py
- test_file2_method1()
- test_file2_method2()
Opción 1) Ejecutar pruebas por coincidencia de subcadenas
Aquí, para ejecutar todas las pruebas que tienen el método 1 en su nombre, tenemos que ejecutar
py.test -k method1 -v -k <expression> is used to represent the substring to match -v increases the verbosity
Entonces ejecutar py.test -k method1 -v le dará el siguiente resultado
test_sample2.py::test_file2_method1 FAILED test_sample1.py::test_file1_method1 FAILED ============================================== FAILURES ============================================== _________________________________________ test_file2_method1 _________________________________________ def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed because x=" + str(x) + " y=" + str(y) E AssertionError: test failed because x=5 y=6 E assert 5 == 6 test_sample2.py:5: AssertionError _________________________________________ test_file1_method1 _________________________________________ @pytest.mark.only def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed because x=" + str(x) + " y=" + str(y) E AssertionError: test failed because x=5 y=6 E assert 5 == 6 test_sample1.py:8: AssertionError ================================= 2 tests deselected by '-kmethod1' ================================== =============================== 2 failed, 2 deselected in 0.02 seconds ===============================
Aquí puede ver hacia el final 2 pruebas deseleccionadas por '-kmethod1' que son test_file1_method2 y test_file2_method2
Intenta correr con varias combinaciones como:-
py.test -k method -v - will run all the four methods py.test -k methods -v – will not run any test as there is no test name matches the substring 'methods'
Opción 2) Ejecutar pruebas por marcadores
Pytest nos permite establecer varios atributos para los métodos de prueba usando marcadores de pytest, @pytest.mark. Para usar marcadores en el archivo de prueba, necesitamos importar pytest en los archivos de prueba.
Aquí aplicaremos diferentes nombres de marcadores a los métodos de prueba y ejecutaremos pruebas específicas basadas en los nombres de los marcadores. Podemos definir los marcadores en cada nombre de prueba usando
@pytest.mark.<name>.
Estamos definiendo los marcadores set1 y set2 en los métodos de prueba y ejecutaremos la prueba usando los nombres de los marcadores. Actualice los archivos de prueba con el siguiente código
prueba_muestra1.py
import pytest @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set2 def test_file1_method2(): x=5 y=6 assert x+1 == y,"test failed"
prueba_muestra2.py
import pytest @pytest.mark.set1 def test_file2_method1(): x=5 y=6 assert x+1 == y,"test failed" assert x == y,"test failed because x=" + str(x) + " y=" + str(y) @pytest.mark.set1 def test_file2_method2(): x=5 y=6 assert x+1 == y,"test failed"
Podemos ejecutar la prueba marcada por
py.test -m <name> -m <name> mentions the marker name
Ejecute py.test -m set1. Esto ejecutará los métodos test_file1_method1, test_file2_method1, test_file2_method2.
Ejecutar py.test -m set2 ejecutará test_file1_method2.
Ejecutar pruebas en paralelo con Pytest
Por lo general, un conjunto de pruebas tendrá múltiples archivos de prueba y cientos de métodos de prueba que llevarán una cantidad considerable de tiempo para ejecutarse. Pytest nos permite ejecutar pruebas en paralelo.
Para eso, primero debemos instalar pytest-xdist ejecutando
pip install pytest-xdist
Puede ejecutar pruebas ahora
py.test -n 4
-n
Accesorios Pytest
Los accesorios se utilizan cuando queremos ejecutar algún código antes de cada método de prueba. Entonces, en lugar de repetir el mismo código en cada prueba, definimos accesorios. Por lo general, los accesorios se utilizan para inicializar las conexiones de la base de datos, pasar la base, etc.
Un método se marca como un accesorio Pytest al marcarlo con
@pytest.fixture
Un método de prueba puede usar un dispositivo Pytest mencionando el dispositivo como un parámetro de entrada.
Cree un nuevo archivo test_basic_fixture.py con el siguiente código
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc] def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
Aquí
- Tenemos un accesorio llamado supply_AA_BB_CC. Este método devolverá una lista de 3 valores.
- Tenemos 3 métodos de prueba que comparan cada uno de los valores.
Cada una de las funciones de prueba tiene un argumento de entrada cuyo nombre coincide con un dispositivo disponible. Pytest luego invoca el método de fijación correspondiente y los valores devueltos se almacenarán en el argumento de entrada, aquí la lista [25,35,45]. Ahora los elementos de la lista se están utilizando en los métodos de prueba para la comparación.
Ahora ejecute la prueba y vea el resultado
py.test test_basic_fixture
test_basic_fixture.py::test_comparewithAA FAILED test_basic_fixture.py::test_comparewithBB PASSED test_basic_fixture.py::test_comparewithCC FAILED ============================================== FAILURES ============================================== _________________________________________ test_comparewithAA _________________________________________ supply_AA_BB_CC = [25, 35, 45] def test_comparewithAA(supply_AA_BB_CC): zz=35 > assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" E AssertionError: aa and zz comparison failed E assert 25 == 35 test_basic_fixture.py:10: AssertionError _________________________________________ test_comparewithCC _________________________________________ supply_AA_BB_CC = [25, 35, 45] def test_comparewithCC(supply_AA_BB_CC): zz=35 > assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed" E AssertionError: cc and zz comparison failed E assert 45 == 35 test_basic_fixture.py:16: AssertionError ================================= 2 failed, 1 passed in 0.05 seconds =================================
La prueba test_comparewithBB se pasa desde zz=BB=35, y las 2 pruebas restantes fallan.
El método fixture tiene un alcance solo dentro de ese archivo de prueba en el que está definido. Si tratamos de acceder al accesorio en algún otro archivo de prueba, obtendremos un error que dice que el accesorio ‘supply_AA_BB_CC’ no se encuentra para los métodos de prueba en otros archivos.
Para usar el mismo dispositivo en varios archivos de prueba, crearemos métodos de dispositivo en un archivo llamado conftest.py.
Veamos esto con el siguiente ejemplo de PyTest. Cree 3 archivos conftest.py, test_basic_fixture.py, test_basic_fixture2.py con el siguiente código
concurso.py
import pytest @pytest.fixture def supply_AA_BB_CC(): aa=25 bb =35 cc=45 return [aa,bb,cc]
test_basic_fixture.py
import pytest def test_comparewithAA(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC(supply_AA_BB_CC): zz=35 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
test_basic_fixture2.py
import pytest def test_comparewithAA_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[0]==zz,"aa and zz comparison failed" def test_comparewithBB_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[1]==zz,"bb and zz comparison failed" def test_comparewithCC_file2(supply_AA_BB_CC): zz=25 assert supply_AA_BB_CC[2]==zz,"cc and zz comparison failed"
pytest primero buscará el accesorio en el archivo de prueba y, si no lo encuentra, lo buscará en conftest.py
Ejecute la prueba con py.test -k test_comparewith -v para obtener el resultado que se muestra a continuación
test_basic_fixture.py::test_comparewithAA FAILED test_basic_fixture.py::test_comparewithBB PASSED test_basic_fixture.py::test_comparewithCC FAILED test_basic_fixture2.py::test_comparewithAA_file2 PASSED test_basic_fixture2.py::test_comparewithBB_file2 FAILED test_basic_fixture2.py::test_comparewithCC_file2 FAILED
Prueba parametrizada de Pytest
El propósito de parametrizar una prueba es ejecutar una prueba contra múltiples conjuntos de argumentos. Podemos hacer esto con @pytest.mark.parametrize.
Veremos esto con el siguiente ejemplo de PyTest. Aquí pasaremos 3 argumentos a un método de prueba. Este método de prueba agregará los primeros 2 argumentos y los comparará con el tercer argumento.
Cree el archivo de prueba test_addition.py con el siguiente código
import pytest @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)]) def test_add(input1, input2, output): assert input1+input2 == output,"failed"
Aquí el método de prueba acepta 3 argumentos:entrada1, entrada2, salida. Agrega input1 y input2 y compara con la salida.
Ejecutemos la prueba con py.test -k test_add -v y veamos el resultado
test_addition.py::test_add[5-5-10] PASSED test_addition.py::test_add[3-5-12] FAILED ============================================== FAILURES ============================================== __________________________________________ test_add[3-5-12] __________________________________________ input1 = 3, input2 = 5, output = 12 @pytest.mark.parametrize("input1, input2, output",[(5,5,10),(3,5,12)]) def test_add(input1, input2, output): > assert input1+input2 == output,"failed" E AssertionError: failed E assert (3 + 5) == 12 test_addition.py:5: AssertionError
Puede ver que las pruebas se realizaron 2 veces:una comprobando 5+5 ==10 y otra comprobando 3+5 ==12
test_addition.py::test_add[5-5-10] APROBADO
test_addition.py::test_add[3-5-12] FALLIDO
Pytest Xfail/Omitir pruebas
Habrá algunas situaciones en las que no queremos ejecutar una prueba, o un caso de prueba no es relevante para un momento determinado. En esas situaciones, tenemos la opción de Xfail la prueba u omitir las pruebas
La prueba xfailed se ejecutará, pero no se contará como parte de las pruebas fallidas o aprobadas. No se mostrará ningún rastreo si esa prueba falla. Podemos xfail pruebas usando
@pytest.mark.xfail.
Omitir una prueba significa que la prueba no se ejecutará. Podemos omitir pruebas usando
@pytest.mark.skip.
Edite test_addition.py con el siguiente código
import pytest @pytest.mark.skip def test_add_1(): assert 100+200 == 400,"failed" @pytest.mark.skip def test_add_2(): assert 100+200 == 300,"failed" @pytest.mark.xfail def test_add_3(): assert 15+13 == 28,"failed" @pytest.mark.xfail def test_add_4(): assert 15+13 == 100,"failed" def test_add_5(): assert 3+2 == 5,"failed" def test_add_6(): assert 3+2 == 6,"failed"
Aquí
- test_add_1 y test_add_2 se omiten y no se ejecutarán.
- test_add_3 y test_add_4 son xfailed. Estas pruebas se ejecutarán y formarán parte de las pruebas xfailed (en prueba fallida) o xpassed (en prueba superada). No habrá ningún rastro de fallas.
- test_add_5 y test_add_6 se ejecutarán y test_add_6 informará el error con el rastreo mientras test_add_5 pasa
Ejecute la prueba con py.test test_addition.py -v y vea el resultado
test_addition.py::test_add_1 SKIPPED test_addition.py::test_add_2 SKIPPED test_addition.py::test_add_3 XPASS test_addition.py::test_add_4 xfail test_addition.py::test_add_5 PASSED test_addition.py::test_add_6 FAILED ============================================== FAILURES ============================================== _____________________________________________ test_add_6 _____________________________________________ def test_add_6(): > assert 3+2 == 6,"failed" E AssertionError: failed E assert (3 + 2) == 6 test_addition.py:24: AssertionError ================ 1 failed, 1 passed, 2 skipped, 1 xfailed, 1 xpassed in 0.07 seconds =================
XML de resultados
Podemos crear resultados de prueba en formato XML que podemos enviar a los servidores de integración continua para su posterior procesamiento, etc. Esto se puede hacer por
py.test prueba_muestra1.py -v –junitxml=”resultado.xml”
El result.xml registrará el resultado de la ejecución de la prueba. Encuentre un resultado de muestra.xml a continuación
<?xml version="1.0" encoding="UTF-8"?> <testsuite errors="0" failures="1" name="pytest" skips="0" tests="2" time="0.046"> <testcase classname="test_sample1" file="test_sample1.py" line="3" name="test_file1_method1" time="0.001384973526"> <failure message="AssertionError:test failed because x=5 y=6 assert 5 ==6"> @pytest.mark.set1 def test_file1_method1(): x=5 y=6 assert x+1 == y,"test failed" > assert x == y,"test failed because x=" + str(x) + " y=" + str(y) E AssertionError: test failed because x=5 y=6 E assert 5 == 6 test_sample1.py:9: AssertionError </failure> </testcase> <testcase classname="test_sample1" file="test_sample1.py" line="10" name="test_file1_method2" time="0.000830173492432" /> </testsuite>
De
Pytest Framework probando una API
Ahora crearemos un pequeño marco pytest para probar una API. La API utilizada aquí es gratuita de https://reqres.in/. Este sitio web es solo para proporcionar una API comprobable. Este sitio web no almacena nuestros datos.
Aquí escribiremos algunas pruebas para
- lista de algunos usuarios
- iniciar sesión con usuarios
Crea los siguientes archivos con el código dado
conftest.py:tenga un accesorio que proporcione la URL base para todos los métodos de prueba
import pytest @pytest.fixture def supply_url(): return "https://reqres.in/api"
test_list_user.py:contiene los métodos de prueba para enumerar usuarios válidos e inválidos
- test_list_valid_user comprueba si el usuario ha obtenido datos válidos y verifica la respuesta
- test_list_invaliduser comprueba la búsqueda de usuarios no válidos y verifica la respuesta
import pytest import requests import json @pytest.mark.parametrize("userid, firstname",[(1,"George"),(2,"Janet")]) def test_list_valid_user(supply_url,userid,firstname): url = supply_url + "/users/" + str(userid) resp = requests.get(url) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['data']['id'] == userid, resp.text assert j['data']['first_name'] == firstname, resp.text def test_list_invaliduser(supply_url): url = supply_url + "/users/50" resp = requests.get(url) assert resp.status_code == 404, resp.text
test_login_user.py:contiene métodos de prueba para probar la funcionalidad de inicio de sesión.
- test_login_valid prueba el intento de inicio de sesión válido con correo electrónico y contraseña
- test_login_no_password prueba el intento de inicio de sesión no válido sin pasar la contraseña
- test_login_no_email prueba el intento de inicio de sesión no válido sin pasar el correo electrónico.
import pytest import requests import json def test_login_valid(supply_url): url = supply_url + "/login/" data = {'email':'[email protected]','password':'something'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 200, resp.text assert j['token'] == "QpwL5tke4Pnpja7X", resp.text def test_login_no_password(supply_url): url = supply_url + "/login/" data = {'email':'[email protected]'} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing password", resp.text def test_login_no_email(supply_url): url = supply_url + "/login/" data = {} resp = requests.post(url, data=data) j = json.loads(resp.text) assert resp.status_code == 400, resp.text assert j['error'] == "Missing email or username", resp.text
Ejecute la prueba usando py.test -v
Ver el resultado como
test_list_user.py::test_list_valid_user[1-George] PASSED test_list_user.py::test_list_valid_user[2-Janet] PASSED test_list_user.py::test_list_invaliduser PASSED test_login_user.py::test_login_valid PASSED test_login_user.py::test_login_no_password PASSED test_login_user.py::test_login_no_email PASSED
Actualiza las pruebas y prueba varias salidas
Resumen
En este tutorial de PyTest, cubrimos
- Instalar pytest usando pip install pytest=2.9.1
- Programa pytest simple y ejecútelo con el comando py.test.
- Las declaraciones de aserción, afirmar x==y, devolverán Verdadero o Falso.
- Cómo pytest identifica archivos y métodos de prueba.
- Archivos de prueba que comienzan con test_ o terminando en _test
- Métodos de prueba que comienzan con test
- El comando py.test ejecutará todos los archivos de prueba en esa carpeta y subcarpetas. Para ejecutar un archivo específico, podemos usar el comando py.test
- Ejecutar un subconjunto de métodos de prueba
- La agrupación de nombres de prueba por subcadena matching.py.test -k
-v ejecutará todas las pruebas que tengan en su nombre. - Ejecute la prueba por marcadores. Marque las pruebas usando @pytest.mark.
y ejecute las pruebas usando pytest -m para ejecutar las pruebas marcadas como . - Ejecutar pruebas en paralelo
- Instalar pytest-xdist usando pip install pytest-xdist
- Ejecutar pruebas usando py.test -n NUM donde NUM es el número de trabajadores
- Crear métodos de fijación para ejecutar código antes de cada prueba marcando el método con @pytest.fixture
- El alcance de un método de fijación está dentro del archivo en el que está definido.
- Se puede acceder a un método de fijación a través de múltiples archivos de prueba definiéndolo en el archivo conftest.py.
- Un método de prueba puede acceder a un dispositivo Pytest usándolo como argumento de entrada.
- Parametrización de pruebas para ejecutarlo contra múltiples conjuntos de entradas.
@pytest.mark.parametrize(“input1, input2, output”,[(5,5,10),(3,5,12)] )
def test_add(input1, input2, output):
assert input1+input2 ==output,”failed”
ejecutará la prueba con las entradas (5,5,10) y (3 ,5,12) - Omitir/pruebas xfail usando @pytets.mark.skip y @pytest.mark.xfail
- Cree resultados de prueba en formato XML que cubran los detalles de la prueba ejecutada usando py.test test_sample1.py -v –junitxml=”result.xml”
- Un framework pytest de muestra para probar una API
python
- Cómo instalar WordPress en Google Cloud
- Tutorial del marco de automatización de pruebas de IU codificadas
- ¿Qué es una llave de seguridad de red? ¿Cómo encontrarlo?
- ¿Qué son las llamadas WiFi? ¿Cómo funciona?
- ¿Qué es 6G y qué tan rápido será?
- Cómo instalar un nivelador de muelle
- Prueba de descarga parcial:qué es y cómo funciona
- ¿Qué es la cavitación de la bomba y cómo la evito?
- ¿Qué es la soldadura fuerte de cobre y cómo hacerla?
- ¿Qué es la acumulación de mantenimiento? ¿Cómo superarlo?
- ¿Qué es un probador de tubo de vacío?