Sto refactoring del codice che implementa una formula e voglio farlo test-first, per migliorare le mie capacità di test e lasciare il codice coperto.Come testare la formula multiparametro
Questo particolare codice è una formula che accetta 3 parametri e restituisce un valore. Ho anche alcune tabelle di dati con risultati attesi per diversi input, quindi in teoria potrei scrivere un test di zillion, semplicemente cambiando i parametri di input e verificando i risultati rispetto al valore atteso corrispondente.
Ma ho pensato che ci dovrebbe essere un modo migliore per farlo, e guardando i documenti ho trovato test di parametri parametrizzati.
Quindi, con questo ora so come creare automaticamente i test per i diversi input.
Ma come ottengo il risultato atteso corrispondente per confrontarlo con quello calcolato?
L'unica cosa che sono riuscito a ottenere è una tabella di ricerca statica e un membro statico nel dispositivo di testo che è un indice della tabella di ricerca e viene incrementato in ogni esecuzione. Qualcosa di simile a questo:
#include "gtest/gtest.h"
double MyFormula(double A, double B, double C)
{
return A*B - C*C; // Example. The real one is much more complex
}
class MyTest:public ::testing::TestWithParam<std::tr1::tuple<double, double, double>>
{
protected:
MyTest(){ Index++; }
virtual void SetUp()
{
m_C = std::tr1::get<0>(GetParam());
m_A = std::tr1::get<1>(GetParam());
m_B = std::tr1::get<2>(GetParam());
}
double m_A;
double m_B;
double m_C;
static double ExpectedRes[];
static int Index;
};
int MyTest::Index = -1;
double MyTest::ExpectedRes[] =
{
// C = 1
// B: 1 2 3 4 5 6 7 8 9 10
/*A = 1*/ 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0,
/*A = 2*/ 1.0, 3.0, 5.0, 7.0, 9.0, 11.0, 13.0, 15.0, 17.0, 19.0,
/*A = 3*/ 2.0, 5.0, 8.0, 11.0, 14.0, 17.0, 20.0, 23.0, 26.0, 29.0,
// C = 2
// B: 1 2 3 4 5 6 7 8 9 10
/*A = 1*/ -3.0, -2.0, -1.0, 0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 6.0,
/*A = 2*/ -2.0, 0.0, 2.0, 4.0, 6.0, 8.0, 10.0, 12.0, 14.0, 16.0,
/*A = 3*/ -1.0, 2.0, 5.0, 8.0, 11.0, 14.0, 17.0, 20.0, 23.0, 26.0,
};
TEST_P(MyTest, TestFormula)
{
double res = MyFormula(m_A, m_B, m_C);
ASSERT_EQ(ExpectedRes[Index], res);
}
INSTANTIATE_TEST_CASE_P(TestWithParameters,
MyTest,
testing::Combine(testing::Range(1.0, 3.0), // C
testing::Range(1.0, 4.0), // A
testing::Range(1.0, 11.0) // B
));
È questo un buon approccio o c'è un modo migliore per ottenere il giusto risultato per ogni run previsto?
Grazie. In questo caso, la specifica che devo seguire fornisce la formula più alcune tabelle con i risultati previsti per alcuni valori. Posso essere abbastanza sicuro che se i miei risultati corrispondono a quei tavoli, l'ho fatto bene.In effetti, ho già trovato alcuni valori errati nelle specifiche, grazie ai test. – MikMik
È grandioso. Se si aggiungono i dati del test all'interno della classe di test, il problema sarà, in futuro, se si desidera testare un altro scenario, quindi è necessario aggiornare nuovamente la classe. Ma se si accede ai dati del test da un file esterno, la manutenzione del caso di test verrà ridotta. Perché si aggiornerà quel file flat per aggiungere nuovi dati di test. questo è tutto. Non c'è bisogno di costruire la tua classe e poi di nuovo distribuirla. –
@PritamKarmakar, vuoi dire che la manutenibilità del test case sarà aumentata, giusto? L'impegno richiesto per mantenerlo sarà ridotto. – Alan