Diferència entre revisions de la pàgina «Introducció al testing»
		
		
		
		
		
		
		Salta a la navegació
		Salta a la cerca
		
				
		
		
		
		
		
		
		
		
	
| (Hi ha 2 revisions intermèdies del mateix usuari que no es mostren) | |||
| Línia 178: | Línia 178: | ||
|      assert "No es pot dividir per zero!" in str(excinfo.value) |      assert "No es pot dividir per zero!" in str(excinfo.value) | ||
| − | =  | + | = Exemples de testing amb QtTest a les Qt en C++ = | 
| − | [https://recull.binefa.cat/files/doc/testing/testcalculator.zip Codis del projecte testcalculator] | + | == testcalculator == | 
| + | * [https://recull.binefa.cat/files/doc/testing/testcalculator.zip Codis del projecte testcalculator] | ||
|   // testcalculator.cpp |   // testcalculator.cpp | ||
|   #include <QtTest> |   #include <QtTest> | ||
| Línia 206: | Línia 207: | ||
|   QTEST_APPLESS_MAIN(TestCalculator) // Sense interfície gràfica. Amb GUI està QTEST_MAIN |   QTEST_APPLESS_MAIN(TestCalculator) // Sense interfície gràfica. Amb GUI està QTEST_MAIN | ||
|   #include "testcalculator.moc" |   #include "testcalculator.moc" | ||
| + | == Test unitari == | ||
| + | * [https://recull.binefa.cat/files/doc/testing/00_testUnitari.zip Test unitari] proposat al [https://doc.qt.io/qt-6/qtest-tutorial.html Qt Test Tutorial] | ||
| + | - testqstring.h: | ||
| + |  #ifndef TESTQSTRING_H | ||
| + |  #define TESTQSTRING_H | ||
| + | |||
| + |  #include <QTest> | ||
| + | |||
| + |  class TestQString: public QObject | ||
| + |  { | ||
| + |     Q_OBJECT | ||
| + |  private slots: | ||
| + |     void toUpper(); | ||
| + |  }; | ||
| + | |||
| + |  #endif // TESTQSTRING_H | ||
| + | - testqstring.cpp: | ||
| + |  #include "testqstring.h" | ||
| + | |||
| + |  void TestQString::toUpper() | ||
| + |  { | ||
| + |     QString str = "Hello"; | ||
| + |     // QVERIFY(str.toUpper() == "HELLO"); | ||
| + |     QCOMPARE(str.toUpper(), QString("HELLO")); | ||
| + |  } | ||
| + | |||
| + |  QTEST_MAIN(TestQString) | ||
| + | |||
| = Exemple de testing amb QtTest a QML = | = Exemple de testing amb QtTest a QML = | ||
| [https://recull.binefa.cat/files/doc/testing/test02.zip Codi del projecte test02] | [https://recull.binefa.cat/files/doc/testing/test02.zip Codi del projecte test02] | ||
Revisió de 12:12, 4 abr 2025
Contingut
Primera presa de contacte
- Per a certificar-se:
ISTQB® Certified Tester Foundation Level
unittest
Codi:
# 00_testing_unittest.py
import unittest
# Funció que volem provar
def suma(a, b):
   return a + b
# Classe de tests
class TestSuma(unittest.TestCase):
   def test_suma_positius(self):
       self.assertEqual(suma(2, 3), 5)
   
   def test_suma_negatius(self):
       self.assertEqual(suma(-1, -1), -2)
   
   def test_suma_mixta(self):
       self.assertEqual(suma(5, -3), 2)
   
   def test_suma_zero(self):
       self.assertEqual(suma(0, 0), 0)
# Executar els tests si s'executa directament aquest fitxer
if __name__ == '__main__':
   unittest.main()
Execució de la prova:
python 00_testing_unittest.py
Sortida pel terminal:
.... ---------------------------------------------------------------------- Ran 4 tests in 0.000s OK
Forçant un error. Per exemple:
self.assertEqual(suma(-1, -1), -3)
La sortida al terminal seria:
.F.. ====================================================================== FAIL: test_suma_negatius (__main__.TestSuma) ---------------------------------------------------------------------- Traceback (most recent call last): File "/media/emmagatzematge/curs2024-2025/dam/testing/codis/00_testing_unittest.py", line 14, in test_suma_negatius self.assertEqual(suma(-1, -1), -3) AssertionError: -2 != -3 ---------------------------------------------------------------------- Ran 4 tests in 0.001s FAILED (failures=1)
pytest
Heu d'instal·lar pytest
pip install pytest
Si sou a Linux cal afegir la ruta de pytest al PATH. Per exemple, afegint al final de l'arxiu .basrc de la carpeta d'usuari (canvieu jordi pel vostre usuari al sistema):
export PATH=$PATH:/home/jordi/.local/bin
Codi d'exemple:
# 01_testing_pytest.py # Funció que volem provar def multiplica(a, b): return a * b # Tests amb pytest (només cal definir funcions que comencin per "test_") def test_multiplica_positius(): assert multiplica(3, 4) == 12 def test_multiplica_negatius(): assert multiplica(-2, -3) == 6 def test_multiplica_mixta(): assert multiplica(5, -2) == -10 def test_multiplica_zero(): assert multiplica(0, 100) == 0
Execució:
pytest 01_testing_pytest.py -v
Sortida pel terminal:
============================= test session starts ============================== platform linux -- Python 3.9.2, pytest-8.3.5, pluggy-1.5.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /media/emmagatzematge/curs2024-2025/dam/testing/codis plugins: anyio-3.3.2 collected 4 items 01_testing_pytest.py::test_multiplica_positius PASSED [ 25%] 01_testing_pytest.py::test_multiplica_negatius PASSED [ 50%] 01_testing_pytest.py::test_multiplica_mixta PASSED [ 75%] 01_testing_pytest.py::test_multiplica_zero PASSED [100%] ============================== 4 passed in 0.03s ===============================
Forçant un error. Per exemple:
assert multiplica(5, -2) == -11
Sortiria pel terminal:
pytest 01_testing_pytest.py -v
============================= test session starts ============================== platform linux -- Python 3.9.2, pytest-8.3.5, pluggy-1.5.0 -- /usr/bin/python3 cachedir: .pytest_cache rootdir: /media/emmagatzematge/curs2024-2025/dam/testing/codis plugins: anyio-3.3.2 collected 4 items 01_testing_pytest.py::test_multiplica_positius PASSED [ 25%] 01_testing_pytest.py::test_multiplica_negatius PASSED [ 50%] 01_testing_pytest.py::test_multiplica_mixta FAILED [ 75%] 01_testing_pytest.py::test_multiplica_zero PASSED [100%] =================================== FAILURES =================================== ____________________________ test_multiplica_mixta _____________________________ def test_multiplica_mixta(): > assert multiplica(5, -2) == -11 E assert -10 == -11 E + where -10 = multiplica(5, -2) 01_testing_pytest.py:15: AssertionError =========================== short test summary info ============================ FAILED 01_testing_pytest.py::test_multiplica_mixta - assert -10 == -11 ========================= 1 failed, 3 passed in 0.10s ==========================
Comprovant múltiples valors. Prova parametritzada
Codi:
# 02_testing_pytest.py
import pytest
def multiplica(a, b):
   return a * b
@pytest.mark.parametrize("a,b,esperat", [
   (3, 4, 12),    # Correcte
   (-2, -3, 5),   # Incorrecte (hauria de ser 6)
   (5, -2, -10),  # Correcte
   (0, 100, 1)    # Incorrecte (hauria de ser 0)
])
def test_multiplica_parametritzada(a, b, esperat):
   assert multiplica(a, b) == esperat
Observeu la sortida al terminal al fer el test:
pytest 02_testing_pytest.py -v
Exemple amb fixtures (dades de prova reutilitzables) en pytest
Codi:
# 03_testing_fixtures_pytest.py import pytest # Definim una fixture (dades de prova) @pytest.fixture def llista_nums(): return [1, 2, 3, 4, 5] # Test que utilitza la fixture def test_suma_llista(llista_nums): assert sum(llista_nums) == 15 # Test que comprova la longitud def test_llargada_llista(llista_nums): assert len(llista_nums) == 5
Testeig d'excepcions
Codi:
# 04_testing_excepcions_pytest.py
import pytest
def divideix(a, b):
   if b == 0:
       raise ValueError("No es pot dividir per zero!")
   return a / b
def test_divideix():
   assert divideix(10, 2) == 5
def test_divideix_per_zero():
   with pytest.raises(ValueError) as excinfo:
       divideix(5, 0)
   assert "No es pot dividir per zero!" in str(excinfo.value)
Exemples de testing amb QtTest a les Qt en C++
testcalculator
// testcalculator.cpp
#include <QtTest>
#include "calculator.h"
class TestCalculator : public QObject
{
   Q_OBJECT
private slots:
   void testSum()
   {
       Calculator calc;
       QCOMPARE(calc.sum(2, 3), 5);
       QCOMPARE(calc.sum(-1, 1), 0);
   }
   
   void testMultiply()
   {
       Calculator calc;
       QCOMPARE(calc.multiply(3, 4), 12);
       QCOMPARE(calc.multiply(-2, -3), 6); // Forçant error canviant a 5
   }
};
QTEST_APPLESS_MAIN(TestCalculator) // Sense interfície gràfica. Amb GUI està QTEST_MAIN
#include "testcalculator.moc"
Test unitari
- Test unitari proposat al Qt Test Tutorial
- testqstring.h:
#ifndef TESTQSTRING_H
#define TESTQSTRING_H
#include <QTest>
class TestQString: public QObject
{
   Q_OBJECT
private slots:
   void toUpper();
};
#endif // TESTQSTRING_H
- testqstring.cpp:
#include "testqstring.h"
void TestQString::toUpper()
{
   QString str = "Hello";
   // QVERIFY(str.toUpper() == "HELLO");
   QCOMPARE(str.toUpper(), QString("HELLO"));
}
QTEST_MAIN(TestQString)
Exemple de testing amb QtTest a QML
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtTest 1.15
...
   TestCase {
       id: testCase
       name: "MathFunctionsTest"
       when: false // Desactivem l'execució automàtica
       // Propietat per emmagatzemar resultats
       property string resultsString: ""
       function runAllTests() {
           resultsString = "";
           var tests = ["test_addNumbers", "test_multiplyNumbers"];
           for (var i = 0; i < tests.length; i++) {
               var testName = tests[i];
               try {
                   this[testName]();
                   resultsString += "✓ PASS: " + testName + "\n";
                   console.log("PASS:", testName);
               } catch (e) {
                   resultsString += "✗ FAIL: " + testName + " - " + e + "\n";
                   console.error("FAIL:", testName, "-", e);
               }
           }
           statusLabel.text = "Tests completats!\n" + resultsString;
       }
       function test_addNumbers() {
           compare(addNumbers(2, 3), 5);
           compare(addNumbers(-1, -1), -2);
       }
       function test_multiplyNumbers() {
           compare(multiply(3, 4), 12);
           compare(multiply(-2, -3), 5); // Error deliberat
       }
       function addNumbers(a, b) {
           return a + b;
       }
       function multiply(a, b) {
           return a * b;
       }
   }

