Best practice per unit test in Magento 1.9


11

Mantengo un sito Magento 1.9 con diversi moduli personalizzati. Alcune funzionalità sono fondamentali per il business e necessitano di alcuni test unitari. Ad esempio un calcolatore del prezzo unitario.

Di solito mi sviluppo in Symfony e preferirei in qualche modo usare PHPUnit (con Composer), se possibile.

Alcune funzionalità si basano sui dati importati in diverse tabelle di database personalizzate, quindi preferirei in qualche modo caricare i dispositivi.

Quindi sto cercando l'approccio migliore per scrivere alcuni test unitari. Accetterò volentieri tutorial o qualcosa di simile. Qualsiasi aiuto è apprezzato.

Risposte:


10

Ho affrontato lo stesso problema qualche tempo fa.

Ho preso in considerazione l'utilizzo del modulo PHPUnit di Ecomdev ma lo trovo difficile da usare e scarsamente documentato (ma adoro ancora ciò che Ivan fa e il suo grande contributo all'ecosistema Magento).

Quindi, con l'aiuto di Vinai, ho finito per sviluppare il seguente modulo del framework di test: https://github.com/digitalpianism/testframework

Lo scopo originale era per i test di integrazione, ma lo sto usando anche per i test unitari. Puoi vederlo in azione qui: https://github.com/digitalpianism/easytoplinks/blob/master/app/code/community/DigitalPianism/EasyToplinks/Test/Unit/Block/Page/Template/LinksTest.php

Per quanto riguarda gli infissi, sto usando i rollback delle transazioni per evitare di creare dati di esempio nel database.


Sembra davvero promettente. Lo proverò. Grazie.
frigg

13

Installazione

Dal momento che Magento 1 non usa il compositore fuori dalla scatola, non penso che faccia una grande differenza se installi phpunit usando compositore o scarichi semplicemente la versione di Phar .
Se usi già compositore per gestire altri moduli o librerie di terze parti nel tuo sito, probabilmente compositore avrà più senso. A meno che non usi PHP7, sarai limitato a una vecchia versione di phpunit (ecco perché ho collegato alla versione 4.8 sopra).

Test di integrazione vs / e / o test unitari

Poiché Magento 1 è un'applicazione così pesante, ha senso separare il bootstrap phpunit in uno per l'integrazione e uno per i test unitari.
Il bootstrap di unit test deve solo inizializzare il caricatore automatico, mentre il bootstrap di test di integrazione deve inizializzare l'intero ambiente dell'applicazione, inclusi il caricamento della configurazione e la connessione db.
A causa di ciò i test di integrazione in Magento tendono a essere molto più lenti dei test unitari (ancora di più rispetto ad altre applicazioni).

Avvio di Magento in phpunit

  • Il caricatore automatico di Magento non è conforme a PSR-0 in quanto genera un'eccezione se non riesce a trovare il file in cui si trova una classe. Ciò interrompe alcuni usi di class_existsin phpunit. Esistono diverse soluzioni alternative (se hacky):

    • Annulla la registrazione del caricatore automatico Magento, avvolgendolo \Varien_Autoload::autoload()in un decoratore ignorando le eccezioni lanciate all'interno e registra il wrapper come nuovo caricatore automatico. Ciò ha una bassa probabilità di conflitti con librerie di terze parti che registrano caricatori automatici e dipendono da un ordine specifico di caricatori automatici.
    • Usa un gestore di errori personalizzato che avvolge quello integrato in Magento 1. I gestori di errori personalizzati inghiottono gli errori innescati dal caricatore automatico Magento. Questa è la soluzione utilizzata dal framework di test di Raphael . Questo sembra essere il più compatibile con altre estensioni di terze parti.
    • Utilizzare l'hack percorso di inclusione per eseguire l'override \Varien_Autoload::autoload()per non generare l'errore se il file non esiste. Ciò tuttavia è in conflitto con diversi moduli che hanno la precedenza sulla stessa classe. Non uso questo approccio da solo.
  • Per evitare errori durante l'avvio della sessione durante i test, impostare semplicemente $_SESSON = []nel bootstrap.

  • Imposta un oggetto di risposta personalizzato Mage::app()->setResponse($testResponse)che estende quello reale ma non invia output o intestazioni.

  • Per reinizializzare Magento tra i test di integrazione che cambiano completamente lo stato di runtime, utilizzare Mage::reset(); Mage::app(). Si noti che successivamente il gestore degli errori dovrà essere ridecorato.

infissi

Per i dispositivi DB tendo ad utilizzare i modelli regolari nei metodi di fissaggio per creare dispositivi, ad es createSimpleProduct($sku). Come ha detto Raphael, utilizzare setUp()e tearDown()avvolgere il test in una transazione che viene ripristinata dopo il test (ad esempio Mage::getSingleton('core/resource')->getConnection('default_setup')->beginTransaction()).

Per i dispositivi di configurazione del negozio, tendo a impostare solo dispositivi in ​​memoria utilizzando Mage::app()->getStore()->setConfig($path, $value).

L' EcomDev_PHPUnitestensione offre anche la possibilità di creare dispositivi DB usando file yaml, ma per me trovo quelli più difficili da mantenere rispetto ai dispositivi creati usando le classi del modello. YMMV.

Test raddoppia

Il registro può essere utilizzato per iniettare doppi di test per oggetti creati tramite Mage::getSingleton(), Mage::getResourceSingleton()e Mage::helper().
Alcuni altri oggetti centrali possono essere impostati Mage::app()(ad es. La richiesta).
Per sostituire le classi create tramite Mage::getModel()o Mage::getResourceModel()con i doppi di test, è necessario utilizzare un wrapper di oggetti di configurazione personalizzato . Vedi questo esempio nel framework di test di Raffaello come realizzare ciò.

Sommario

Una volta avviato Magento, praticamente tutto può essere testato piuttosto bene. Preparati a creare simulazioni profonde a causa della grande quantità di metodo che utilizza il codice core.
Anche se l'installazione è complicata, funziona bene e trovo che i test mi diano molta fiducia e valore, praticamente paragonabili a una suite di test per un'app Symphony.


Non l'ho mai provato ma perché non usare Magento Test Framework? ( docs.magento.com/m1/ce/user_guide/magento/… )
Fra

3
Sì, l'ho provato, ma è un test funzionale (non unità o integrazione), è lento, è complesso e i test tendono ad essere traballanti e fragili. Tutto sommato ho considerato il tempo che ho trascorso con esso uno spreco.
Vinai,

@Vinai So che è tardi, ma generalmente in un controller ci sono chiamate al modello e alle raccolte, che durante i test non ci serviranno. Sto usando il tuo framework di Test (DigitalPianism), e lì possiamo TestDouble i modelli ma mentre faccio una richiesta per un'azione del controller che a sua volta usa un modello, come posso prendere in giro quella chiamata modello / raccolta?
Arqam,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.