2014-08-29 15 views
7

Come posso rimuovere completamente una classe dalla memoria in Ruby?Come si ripristina una definizione di classe in Ruby?

Ho due file con cui sto lavorando:

# foo.rb 
require 'expensive_library' 

class Foo < ExpensiveLibrary::Plugin 
    ... 
end 

e:

# foo_tests.rb 
require 'foo' 
require 'test/unit' 

class foo_tests < Test::Unit::TestCase 
    def test_foo_meets_spec_1 
    ... 
    end 
    def test_foo_meets_deprecated_spec 
    ... 
    end 
end 

ExpensiveLibrary è costoso; ci vogliono più di 15 secondi per caricare. È troppo lungo per eseguire ripetutamente i test durante lo sviluppo (il resto della suite di test richiede meno di 1 secondo).

Ho lavorato intorno al tempo di caricamento della libreria costosa avviando Pry e scrivendo una funzione che carica i due file e chiama Test::Unit:Autorunner.run. Questo ha ancora una pausa di 15 secondi nella prima esecuzione dei test, ma i successivi test durano meno di 1 secondo ciascuno.

Tuttavia, ci sono due problemi:

  1. leva lamenta tutti i metodi su Foo e Foo_tests essere ridefiniti
  2. quando rimuovo un metodo dal file di origine, rimane definita nel mio ambiente di prova, generando fallimenti spuri.

Sulla base di altre questioni Stack Overflow (come "How to undefine class in Ruby?"), ho provato a chiamare Object.constants.remove(:Foo) e Object.constants.remove(:Foo_tests). Non riesco più a ottenere gli errori ridefiniti del metodo, ma ora l'autorunner esegue i test più volte, inclusi i test rimossi.

Quello che voglio è eseguire i test modificati senza ricaricare ExpensiveLibrary. L'indefinimento delle classi di test è il modo in cui vedo farlo, ma non so come. Altre soluzioni potrebbero essere migliori.

+0

Grazie per la modifica. –

risposta

0

OK, solo spitballing qui, perché non sono certo esattamente quello che stai cercando, ma hai provato undef o undef_method? Non funzionano direttamente sulle classi, ma se non trovi i metodi che chiamano i test che non vuoi vengano eseguiti forse funzionerà per te?

0

È possibile effettuare l'hacking con percorsi di caricamento (Adding a directory to $LOAD_PATH (Ruby)).

  • creare qualche cartella come ./tests/fake_implementations/
  • aggiungerlo a $ LOAD_PATHS
  • aggiungere Non ci depositare expensive_library.rb con qualche leggero falso attuazione ExpensiveLibrary
  • poi require 'expensinsive_library' caricherà questo file al posto di quello originale.
1

Mi sembra che quello che stai cercando sia un preloader come o anche uno più specifico come rspec-preloader. Quando si utilizza un preloader, si dovrà richiedere il file 'pippo' in un file spec/spec_helper.rb, che probabilmente avete già:

# spec/spec_helper.rb 
require 'foo' 

# ... 

Il spec_helper dovrebbe caricare l'intero ambiente app. Probabilmente, è più costoso quando si eseguono i test uno alla volta.Ma usando un preloader, devi solo richiedere tutto il codice una volta.

Problemi correlati