From 782406482d5887211d48719dfaa9a0cd70947c35 Mon Sep 17 00:00:00 2001 From: Vincent Jacques Date: Thu, 23 Feb 2012 18:57:26 +0100 Subject: [PATCH 1/2] On the way to repaly-able integration tests --- IntegrationTest.py | 127 +++++++++++++++++++++++++++++++++------------ 1 file changed, 95 insertions(+), 32 deletions(-) diff --git a/IntegrationTest.py b/IntegrationTest.py index 6e418c53..b307005e 100644 --- a/IntegrationTest.py +++ b/IntegrationTest.py @@ -1,42 +1,105 @@ #!/bin/env python +import sys +import httplib + from github import Github -try: - import GithubCredentials -except ImportError: - print "Please create a 'GithubCredentials.py' file containing:" - print "login = ''" - print "password = ''" - exit( 1 ) -def dumpUser( u ): - print u.login, "(", u.name, ")" - print " Repos:" - for r in u.get_repos(): - print " ", r.name, - if r.fork: - print "<-", r.parent.owner.login + "/" + r.parent.name, - print "<-", r.source.owner.login + "/" + r.source.name, +class RecordingHttpResponse( object ): + def __init__( self, res ): + self.__res = res + + @property + def status( self ): + return self.__res.status + + def getheaders( self ): + return self.__res.getheaders() + + def read( self ): + return self.__res.read() + +class RecordingHttpsConnection: + __realHttpsConnection = httplib.HTTPSConnection + + def __init__( self, host, strict ): + self.__cnx = self.__realHttpsConnection( host, strict = strict ) + + def request( *args, **kwds ): + return self.__cnx.request( *args, **kwds ) + + def getresponse( self ): + return RecordingHttpResponse( self.__cnx.getresponse() ) + + def close( self ): + return self.__cnx.close() + +class IntegrationTest: + def main( self ): + if len( sys.argv ) == 2 and sys.argv[ 1 ] == "--record": + print "Record mode: I'm really going to do requests to github.com. Please type 'yes' and return" + confirm = sys.stdin.readline().strip() + if confirm != "yes": + exit( 1 ) + self.record() + else: + self.replay() + + exit() + + def record( self ): + g = self.prepareRecord() + self.playScenario( g ) + + def replay( self ): + g = self.prepareReplay() + self.playScenario( g ) + + def prepareRecord( self ): + try: + import GithubCredentials + g = Github( GithubCredentials.login, GithubCredentials.password ) + httplib.HTTPSConnection = RecordingHttpsConnection + return g + except ImportError: + print "Please create a 'GithubCredentials.py' file containing:" + print "login = ''" + print "password = ''" + exit( 1 ) + + def playScenario( self, g ): + print g.get_user().name + + def dumpUser( u ): + print u.login, "(", u.name, ")" + print " Repos:" + for r in u.get_repos(): + print " ", r.name, + if r.fork: + print "<-", r.parent.owner.login + "/" + r.parent.name, + print "<-", r.source.owner.login + "/" + r.source.name, + print + print " Watched:", ", ".join( r.name for r in u.get_watched() ) + print " Organizations:", ", ".join( o.login for o in u.get_orgs() ) + print " Following:", ", ".join( f.login for f in u.get_following() ) + print " Followers:", ", ".join( f.login for f in u.get_followers() ) print - print " Watched:", ", ".join( r.name for r in u.get_watched() ) - print " Organizations:", ", ".join( o.login for o in u.get_orgs() ) - print " Following:", ", ".join( f.login for f in u.get_following() ) - print " Followers:", ", ".join( f.login for f in u.get_followers() ) - print -def dumpOrganization( o ): - print o.login, "(", o.name, ")" - print " Members:", ", ".join( u.login for u in o.get_members() ) - print " Repos:", ", ".join( r.name for r in o.get_repos() ) - print + def dumpOrganization( o ): + print o.login, "(", o.name, ")" + print " Members:", ", ".join( u.login for u in o.get_members() ) + print " Repos:", ", ".join( r.name for r in o.get_repos() ) + print -def dumpRepository( r ): - print r.owner.login + "/" + r.name - print " Collaborators:", ", ".join( u.login for u in r.get_collaborators() ) - print " Contributors:", ", ".join( u.login for u in r.get_contributors() ) - print " Watchers:", ", ".join( u.login for u in r.get_watchers() ) - print " Forks:", ", ".join( f.owner.login + "/" + f.name for f in r.get_forks() ) - print + def dumpRepository( r ): + print r.owner.login + "/" + r.name + print " Collaborators:", ", ".join( u.login for u in r.get_collaborators() ) + print " Contributors:", ", ".join( u.login for u in r.get_contributors() ) + print " Watchers:", ", ".join( u.login for u in r.get_watchers() ) + print " Forks:", ", ".join( f.owner.login + "/" + f.name for f in r.get_forks() ) + print + +IntegrationTest().main() g = Github( GithubCredentials.login, GithubCredentials.password ) From d8e2177fb8735579e83bfb60d445d801cb33c22c Mon Sep 17 00:00:00 2001 From: Vincent Jacques Date: Thu, 23 Feb 2012 19:11:34 +0000 Subject: [PATCH 2/2] Record and replay integration tests! --- .gitignore | 1 + IntegrationTest.py | 154 +++++++++++++++++++++++++++------------------ 2 files changed, 95 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index 8a9af146..2afca92c 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ GithubCredentials.py .coverage /dist /MANIFEST +ReplayDataForIntegrationTest.txt diff --git a/IntegrationTest.py b/IntegrationTest.py index b307005e..00dc728e 100644 --- a/IntegrationTest.py +++ b/IntegrationTest.py @@ -6,38 +6,72 @@ import httplib from github import Github class RecordingHttpResponse( object ): - def __init__( self, res ): - self.__res = res - - @property - def status( self ): - return self.__res.status + def __init__( self, file, res ): + self.status = res.status + self.__headers = res.getheaders() + self.__output = res.read() + file.write( str( self.status ) + "\n" ) + file.write( str( self.__headers ) + "\n" ) + file.write( str( self.__output ) + "\n" ) def getheaders( self ): - return self.__res.getheaders() + return self.__headers def read( self ): - return self.__res.read() + return self.__output class RecordingHttpsConnection: __realHttpsConnection = httplib.HTTPSConnection - def __init__( self, host, strict ): - self.__cnx = self.__realHttpsConnection( host, strict = strict ) + def __init__( self, file, *args, **kwds ): + self.__file = file + self.__cnx = self.__realHttpsConnection( *args, **kwds ) - def request( *args, **kwds ): - return self.__cnx.request( *args, **kwds ) + def request( self, verb, url, input, headers ): + self.__cnx.request( verb, url, input, headers ) + del headers[ "Authorization" ] # Do not let sensitive info in git :-p + self.__file.write( verb + " " + url + " " + str( headers ) + " " + input + "\n" ) def getresponse( self ): - return RecordingHttpResponse( self.__cnx.getresponse() ) + return RecordingHttpResponse( self.__file, self.__cnx.getresponse() ) def close( self ): + self.__file.write( "\n" ) return self.__cnx.close() +class ReplayingHttpResponse( object ): + def __init__( self, file ): + self.status = int( file.readline().strip() ) + self.__headers = eval( file.readline().strip() ) + self.__output = file.readline().strip() + + def getheaders( self ): + return self.__headers + + def read( self ): + return self.__output + +class ReplayingHttpsConnection: + def __init__( self, file ): + self.__file = file + + def request( self, verb, url, input, headers ): + del headers[ "Authorization" ] + assert self.__file.readline().strip() == verb + " " + url + " " + str( headers ) + " " + input + + def getresponse( self ): + return ReplayingHttpResponse( self.__file ) + + def close( self ): + self.__file.readline() + class IntegrationTest: + __fileName = "ReplayDataForIntegrationTest.txt" + def main( self ): if len( sys.argv ) == 2 and sys.argv[ 1 ] == "--record": print "Record mode: I'm really going to do requests to github.com. Please type 'yes' and return" + sys.stdout.flush() confirm = sys.stdin.readline().strip() if confirm != "yes": exit( 1 ) @@ -48,29 +82,61 @@ class IntegrationTest: exit() def record( self ): - g = self.prepareRecord() - self.playScenario( g ) + self.prepareRecord() + self.playScenario() def replay( self ): - g = self.prepareReplay() - self.playScenario( g ) + self.prepareReplay() + self.playScenario() def prepareRecord( self ): try: import GithubCredentials - g = Github( GithubCredentials.login, GithubCredentials.password ) - httplib.HTTPSConnection = RecordingHttpsConnection - return g + self.g = Github( GithubCredentials.login, GithubCredentials.password ) + file = open( self.__fileName, "w" ) + httplib.HTTPSConnection = lambda *args, **kwds: RecordingHttpsConnection( file, *args, **kwds ) except ImportError: print "Please create a 'GithubCredentials.py' file containing:" print "login = ''" print "password = ''" exit( 1 ) - def playScenario( self, g ): - print g.get_user().name + def prepareReplay( self ): + try: + file = open( self.__fileName ) + httplib.HTTPSConnection = lambda *args, **kwds: ReplayingHttpsConnection( file ) + self.g = Github( "login", "password" ) + except IOError: + print "Please re-run this script with argument '--record' to be able to replay the integration tests based on recorded first execution" + exit( 1 ) - def dumpUser( u ): + def playScenario( self ): + self.doSomeReads() + self.doSomeWrites() + + def doSomeReads( self ): + self.dumpUser( self.g.get_user() ) + jacquev6 = self.g.get_user( "jacquev6" ) + self.dumpUser( jacquev6 ) + self.dumpOrganization( self.g.get_organization( "github" ) ) + self.dumpRepository( jacquev6.get_repo( "PyGithub" ) ) + + def doSomeWrites( self ): + self.doSomeWritesTuUser() + + def doSomeWritesTuUser( self ): + u = self.g.get_user() + oldBio = u.bio + u.edit( bio = oldBio + " (Edited by PyGithub)" ) + u.edit( bio = oldBio ) + jacquev6 = self.g.get_user( "jacquev6" ) + u.remove_from_following( jacquev6 ) + u.add_to_following( jacquev6 ) + PyGithub = jacquev6.get_repo( "PyGithub" ) + u.remove_from_watched( PyGithub ) + u.add_to_watched( PyGithub ) + + def dumpUser( self, u ): print u.login, "(", u.name, ")" print " Repos:" for r in u.get_repos(): @@ -84,54 +150,22 @@ class IntegrationTest: print " Following:", ", ".join( f.login for f in u.get_following() ) print " Followers:", ", ".join( f.login for f in u.get_followers() ) print + sys.stdout.flush() - def dumpOrganization( o ): + def dumpOrganization( self, o ): print o.login, "(", o.name, ")" print " Members:", ", ".join( u.login for u in o.get_members() ) print " Repos:", ", ".join( r.name for r in o.get_repos() ) print + sys.stdout.flush() - def dumpRepository( r ): + def dumpRepository( self, r ): print r.owner.login + "/" + r.name print " Collaborators:", ", ".join( u.login for u in r.get_collaborators() ) print " Contributors:", ", ".join( u.login for u in r.get_contributors() ) print " Watchers:", ", ".join( u.login for u in r.get_watchers() ) print " Forks:", ", ".join( f.owner.login + "/" + f.name for f in r.get_forks() ) print + sys.stdout.flush() IntegrationTest().main() - -g = Github( GithubCredentials.login, GithubCredentials.password ) - -# Reads -# ===== -u = g.get_user() -# o = g.get_organization( "" ) -jacquev6 = g.get_user( "jacquev6" ) -PyGithub = jacquev6.get_repo( "PyGithub" ) - -dumpUser( u ) -dumpUser( jacquev6 ) -dumpOrganization( g.get_organization( "github" ) ) -dumpRepository( PyGithub ) - -# Writes (to user) -# ================ -# u.edit( bio = u.bio + "(Edited by PyGithub)" ) - -# u.remove_from_following( jacquev6 ) -# u.add_to_following( jacquev6 ) - -# u.remove_from_watched( PyGithub ) -# u.add_to_watched( PyGithub ) - -# dumpRepository( u.create_repo( name = "TestGithubApi", description = "Created by a Python script!", has_wiki = False ) ) -# dumpRepository( u.create_fork( PyGithub ) ) - - -# Writes (to organization) -# ======================== -# o.edit( location = "Paris, France" ) - -# dumpRepository( o.create_repo( name = "TestGithubApi", description = "Created by a Python script!", has_wiki = False ) ) -# dumpRepository( o.create_fork( PyGithub ) )