Path: csiph.com!usenet.pasdenom.info!aioe.org!news.stack.nl!newsfeed.xs4all.nl!newsfeed6.news.xs4all.nl!xs4all!post.news.xs4all.nl!not-for-mail Return-Path: X-Original-To: python-list@python.org Delivered-To: python-list@mail.python.org X-Spam-Status: OK 0.000 X-Spam-Evidence: '*H*': 1.00; '*S*': 0.00; 'schema': 0.05; '*args,': 0.07; 'main()': 0.07; 'option,': 0.07; 'statically': 0.07; 'subject:adding': 0.07; 'suppose': 0.07; 'variable,': 0.07; '**kwargs):': 0.09; 'argument,': 0.09; 'exception,': 0.09; 'part,': 0.09; 'todo:': 0.09; 'url:github': 0.09; 'cc:addr:python- list': 0.10; 'def': 0.10; 'cases': 0.15; 'represents': 0.15; 'argument.': 0.16; 'copytree': 0.16; 'csv': 0.16; 'dest)': 0.16; 'effect,': 0.16; 'hard-coded': 0.16; 'replaced.': 0.16; 'to:addr:pearwood.info': 0.16; 'to:addr:steve+comp.lang.python': 0.16; "to:name:steven d'aprano": 0.16; 'config': 0.17; 'implementing': 0.17; 'hack': 0.18; 'bit': 0.21; 'libraries': 0.22; 'cc:2**0': 0.23; 'example': 0.23; 'this:': 0.23; "i've": 0.23; 'cc:no real name:2**0': 0.24; 'machine': 0.24; 'pass': 0.25; 'cc:addr:python.org': 0.25; 'header:In-Reply-To:1': 0.25; 'looks': 0.26; 'creating': 0.26; 'first,': 0.27; 'message- id:@mail.gmail.com': 0.27; 'run': 0.28; '(perhaps': 0.29; "d'aprano": 0.29; 'giant': 0.29; 'steven': 0.29; 'skip:_ 10': 0.29; 'probably': 0.29; 'class': 0.29; "i'm": 0.29; 'maybe': 0.29; 'connection': 0.30; 'that.': 0.30; 'e.g.': 0.30; 'error': 0.30; 'code': 0.31; 'point': 0.31; '(and': 0.32; 'file': 0.32; 'generally': 0.32; 'could': 0.32; 'skip:s 30': 0.33; 'done,': 0.33; 'entry': 0.33; 'received:google.com': 0.34; 'generic': 0.35; 'open': 0.35; 'received:209.85': 0.35; 'there': 0.35; 'really': 0.36; 'but': 0.36; "i'll": 0.36; 'test': 0.36; 'should': 0.36; 'problems': 0.36; 'possible': 0.37; 'virtual': 0.37; 'received:209': 0.37; 'data': 0.37; 'subject:: ': 0.38; 'files': 0.38; 'object': 0.38; 'some': 0.38; 'instead': 0.39; 'system.': 0.39; 'easily': 0.39; 'application': 0.40; 'header:Received:5': 0.40; 'help': 0.40; 'think': 0.40; 'your': 0.60; 'easy': 0.60; 'solve': 0.62; 'more': 0.63; 'skip:c 50': 0.66; 'answer.': 0.71; 'connection,': 0.71; 'generations,': 0.84; 'mock': 0.84; 'stuff:': 0.84; 'subject:mode': 0.84; 'dirty': 0.91; 'hardest': 0.91; 'demand': 0.96 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=mime-version:in-reply-to:references:date:message-id:subject:from:to :cc:content-type; bh=NXXcNj+u2zv/siEG/Rs2aS9GdTQg1BbA3mIEo6wvImE=; b=HPkiq35FXJp7xRWJbRD5fWjEOF9hxcXH3UTnEuk/0M7uevS9O9/uL3RuZ+vIkJdMq5 C1tKkPlJchTR8RITIkJFGOS7B3eRLURZ30duccpdU5EV8Rpau13KQwiVrryYfk+yImgu l9c8lDGkgbJdzsNUqZQwboqYXBzRw8v7phNONe+iU/bPSYB76ugZgBbDMso6F3fhpQI4 k4P4eqA7To/bgVlIDl1R5ud0dSxlJl3LLVlYZhuykfrIFunoAeRInscNaSLt/He7+lIl hoaNiZah+jST1oE/s1CacIVAl2XViBf2HD+HnVKzWqkvXW+zkWyRlH6W+Zg2LLbYUcKh lbFA== MIME-Version: 1.0 In-Reply-To: <4ff44823$0$29988$c3e8da3$5496439d@news.astraweb.com> References: <4ff44823$0$29988$c3e8da3$5496439d@news.astraweb.com> Date: Wed, 4 Jul 2012 14:59:55 +0100 Subject: Re: adding a simulation mode From: andrea crotti To: "Steven D'Aprano" Content-Type: text/plain; charset=ISO-8859-1 Cc: python-list@python.org X-BeenThere: python-list@python.org X-Mailman-Version: 2.1.12 Precedence: list List-Id: General discussion list for the Python programming language List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Newsgroups: comp.lang.python Message-ID: Lines: 74 NNTP-Posting-Host: 2001:888:2000:d::a6 X-Trace: 1341410397 news.xs4all.nl 6872 [2001:888:2000:d::a6]:48737 X-Complaints-To: abuse@xs4all.nl Xref: csiph.com comp.lang.python:24862 2012/7/4 Steven D'Aprano : > > Then, have your code accept the thing as an argument. > > E.g. instead of having a hard-coded database connection, allow the > database connection to be set (perhaps as an argument, perhaps as a > config option, etc.). > > There are libraries to help with mocks, e.g.: > > http://garybernhardt.github.com/python-mock-comparison/ Ah yes this part is already done, I pass an object to the entry point of the program which represents the database connection, which looks like this: class MockMysqlEngine(MySqlEngine): # TODO: make the engine more generic would avoid this dirty hack def __init__(self, *args, **kwargs): # self.engine = create_engine('sqlite:////home/andrea/testdb.sqlite', echo=True) self.engine = create_engine('sqlite://', echo=True) self.meta = MetaData(bind=self.engine) self.session_maker = sessionmaker(bind=self.engine) Now I populate statically the schema and populate with some test data too, but I'm also implementing a weay to just pass some CSV files so that other people can easily write some test cases with some other possible database configurations. (And I use mock for a few other things) > > >> For example >> >> copytree(src, dest) becomes: >> if not PRETEND_ONLY: >> copytree(src, dest) > > Ewww :( > > Mocking the file system is probably the hardest part, because you > generally don't have a "FileSystem" object available to be replaced. In > effect, your program has one giant global variable, the file system. > Worse, it's not even a named variable, it's hard-coded everywhere you use > it. > > I don't know of any good solution for that. I've often thought about it, > but don't have an answer. > > I suppose you could monkey-patch a bunch of stuff: > > if ONLY_PRETEND: > open = my_mock_open > copytree = my_mock_copytree > # etc. > main() # run your application > > > > but that would also be painful. > Yes there is no easy solution apparently.. But I'm also playing around with vagrant and virtual machine generations, suppose I'm able to really control what will be on the machine at time X, creating it on demand with what I need, it might be a good way to solve my problems (a bit overkill and slow maybe though). I'll try the sys.excepthook trick first, any error should give me an exception, so if I catch them all I think it might work already..