Garantire l'output del programma è sempre lo stesso [chiuso]

0

Sto lavorando su un programma LOC + 10k, e ho bisogno di assicurarmi che il suo output sia sempre lo stesso per un dato input. Il programma consiste di dozzine di moduli e classi, ereditati da MainClass . (Gli esempi di seguito sono molto semplificati rispetto al codice reale.)

Inizialmente ho creato test per garantire che più istanze di MainClass avessero lo stesso risultato per un dato input.

def check_consistent_instances(input_dict):
    """Checks if all results for given input are the same."""
    first_instance_result = MainClass(input_dict).result()

    for i in range(10000):
        result = MainClass(input_dict).result()    
        if first_instance_result != result:
            raise Exception('Different result detected!!')

Questo tuttavia non può rilevare risultati diversi in più esecuzioni causate da insiemi / dettare con un ordine diverso a causa di un nuovo hash seed in ogni esecuzione (questo potrebbe in alcuni rari casi influenzare l'output).

Ad esempio:

class MyClass(object):
    AVAILABLE_MONEY = 6

    ITEMS_CATALOG = {'a': 5, 'b': 5, 'c': 5, 'd': 5, 'e': 3}

    def buy_most_expensive(self):
        """Deducts the most expensive items from the available money."""


        for i in self.ITEMS_CATALOG:
        # Assume I made a mistake here! I should have used sorted(self.ITEMS_CATALOG, key=lambda x: self.ITEMS_CATALOG[x])
        # but accidentally i used only self.ITEMS_CATALOG.
            cost = self.ITEMS_CATALOG[i]

            if cost <= self.AVAILABLE_MONEY:
                self.AVAILABLE_MONEY -= cost

Il codice come sopra passerebbe il mio check_consistent_instances() test, poiché su ogni esecuzione il PYTHONHASHSEED avrebbe un valore specifico e tutti i risultati sarebbero gli stessi durante un'esecuzione specifica . I risultati sarebbero diversi solo tra diverse esecuzioni.

Domanda:
Quali sono le migliori pratiche quando si tratta di verificare se i risultati di un programma sono coerenti?

    
posta Fermi paradox 23.08.2015 - 11:14
fonte

2 risposte

2

Dato che hai scritto nel tuo commento che vuoi rendere stabile l'output del programma invariato quando non viene modificato tra due esecuzioni, hai già escluso "modifiche accidentali alle variabili del modulo" - senza alcuna modifica , non ci possono essere "modifiche accidentali".

Il link SO che hai postato nella tua domanda ha menzionato come inizializzare il seed hash di Python ad un valore fisso, quindi questa dovrebbe essere ovviamente la prossima cosa da fare. La stessa misura si applica quando il tuo programma usa direttamente qualche tipo di numeri pseudo casuali.

Quindi ciò che rimane sono i luoghi del tuo programma in cui utilizza alcuni input esterni come dati da un orologio, o dati da processi esterni al tuo programma (come chiamare una funzione OS che ti dice quanti altri processi sono attualmente in esecuzione sulla macchina ), questi sono AFAIK le uniche cose in cui il non-determinismo può essere introdotto in un tipico programma Python. In realtà non conosciamo le parti interne del tuo programma, ma dovresti saperlo. Quindi la migliore raccomandazione che posso darti: fai un'ispezione completa se il tuo programma contiene chiamate a funzioni esterne del tipo che ho citato ed evita di usarle all'interno della parte del programma in cui viene calcolato l'output.

Inoltre, per scoprire se hai trascurato qualcosa nella tua ispezione, dovresti prendere in considerazione la creazione di regression test automatici (non necessariamente test unitari, ma molte persone mescolano questi termini). Scegli una serie di dati di input ben scelti, esegui il programma per produrre l'output desiderato e scrivi un semplice strumento di comparazione che ti consente di rilevare se una nuova esecuzione del programma produce ancora l'output precedente. Questa è anche la tecnica standard per rilevare se l'output di "versione 1.1" del tuo programma è ancora lo stesso dell'output di "versione 1.0", quando le modifiche da 1.0 a 1.1 non avrebbero dovuto influenzare i risultati.

    
risposta data 24.08.2015 - 07:59
fonte
1

Vorrei aggiungere una serie di test unitari per i singoli moduli e utilizzare qualcosa come Jenkins per compilare ed eseguire i test ogni volta che si apportano modifiche al codice. Se stai riscontrando variazioni durante l'esecuzione, questo dovrebbe aiutarti a restringerlo in modo da poter modificare la logica del modulo per garantire la ripetibilità.

    
risposta data 24.08.2015 - 04:14
fonte

Leggi altre domande sui tag