From 1625a645de547b29e9de0f40d40cbcdc4a72f29d Mon Sep 17 00:00:00 2001 From: Vincent Jacques Date: Tue, 8 May 2012 10:42:12 +0100 Subject: [PATCH] Start to rewrite integration test --- NewIntegrationTest.py | 118 ++++++++++++++++++ .../AuthenticatedUser.Attributes.txt | 4 + github/Github.UnitTest.py | 118 ------------------ github/Requester.UnitTest.py | 64 ---------- run_tests.sh | 27 +--- 5 files changed, 126 insertions(+), 205 deletions(-) create mode 100644 NewIntegrationTest.py create mode 100644 ReplayDataForNewIntegrationTest/AuthenticatedUser.Attributes.txt delete mode 100644 github/Github.UnitTest.py delete mode 100644 github/Requester.UnitTest.py diff --git a/NewIntegrationTest.py b/NewIntegrationTest.py new file mode 100644 index 00000000..56931b6d --- /dev/null +++ b/NewIntegrationTest.py @@ -0,0 +1,118 @@ +#!/bin/env python + +import os +import sys +import unittest +import httplib +import traceback + +import github + +class RecordReplayException( Exception ): + pass + +class RecordingHttpsConnection: + class HttpResponse( object ): + 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.__headers + + def read( self ): + return self.__output + + __realHttpsConnection = httplib.HTTPSConnection + + def __init__( self, file, *args, **kwds ): + self.__file = file + self.__cnx = self.__realHttpsConnection( *args, **kwds ) + + def request( self, verb, url, input, headers ): + print verb, url + 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 RecordingHttpsConnection.HttpResponse( self.__file, self.__cnx.getresponse() ) + + def close( self ): + self.__file.write( "\n" ) + return self.__cnx.close() + +class ReplayingHttpsConnection: + class HttpResponse( 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 + + def __init__( self, file ): + self.__file = file + + def request( self, verb, url, input, headers ): + del headers[ "Authorization" ] + expectation = self.__file.readline().strip() + while expectation.startswith( "#" ): + self.__file.readline() + self.__file.readline() + self.__file.readline() + self.__file.readline() + expectation = self.__file.readline().strip() + if expectation != verb + " " + url + " " + str( headers ) + " " + input: + print "Expected [", expectation, "] but got [", verb + " " + url + " " + str( headers ) + " " + input, "]" + raise RecordReplayException( "This test has been changed since last record. Please re-run this script with argument '--record'" ) + + def getresponse( self ): + return ReplayingHttpsConnection.HttpResponse( self.__file ) + + def close( self ): + self.__file.readline() + +class TestCase( unittest.TestCase ): + def setUp( self ): + unittest.TestCase.setUp( self ) + self.__file = None + httplib.HTTPSConnection = lambda *args, **kwds: ReplayingHttpsConnection( self.__openFile() ) + self.g = github.Github( "login", "password" ) + + def tearDown( self ): + unittest.TestCase.tearDown( self ) + self.__file.close() + + def __openFile( self ): + for ( _, _, functionName, _ ) in traceback.extract_stack(): + if functionName.startswith( "test" ): + fileName = os.path.join( "ReplayDataForNewIntegrationTest", self.__class__.__name__ + "." + functionName[ 4: ] + ".txt" ) + if self.__file is None: + self.__file = open( fileName ) + return self.__file + +class AuthenticatedUser( TestCase ): + def setUp( self ): + TestCase.setUp( self ) + self.u = self.g.get_user() + + def tearDown( self ): + TestCase.tearDown( self ) + + def testAttributes( self ): + self.assertEqual( self.u.login, "jacquev6" ) + self.assertEqual( self.u.name, "Vincent Jacques" ) + +if len( sys.argv ) > 1: + pass +else: + unittest.main() diff --git a/ReplayDataForNewIntegrationTest/AuthenticatedUser.Attributes.txt b/ReplayDataForNewIntegrationTest/AuthenticatedUser.Attributes.txt new file mode 100644 index 00000000..5494b999 --- /dev/null +++ b/ReplayDataForNewIntegrationTest/AuthenticatedUser.Attributes.txt @@ -0,0 +1,4 @@ +GET /user {} null +200 +[('status', '200 OK'), ('x-ratelimit-remaining', '4980'), ('x-ratelimit-limit', '5000'), ('content-length', '801'), ('server', 'nginx/1.0.12'), ('connection', 'keep-alive'), ('etag', '"b20002247c9333d5a126bde09e47f03f"'), ('date', 'Thu, 01 Mar 2012 19:36:16 GMT'), ('content-type', 'application/json; charset=utf-8')] +{"owned_private_repos":5,"type":"User","private_gists":2,"created_at":"2010-07-09T06:10:06Z","location":"Paris, France","plan":{"private_repos":5,"collaborators":1,"name":"micro","space":614400},"company":"Criteo","collaborators":0,"followers":12,"email":"vincent@vincent-jacques.net","hireable":false,"url":"https://api.github.com/users/jacquev6","blog":"http://vincent-jacques.net","bio":"","following":24,"html_url":"https://github.com/jacquev6","name":"Vincent Jacques","total_private_repos":5,"disk_usage":17252,"public_repos":15,"gravatar_id":"b68de5ae38616c296fa345d2b9df2225","avatar_url":"https://secure.gravatar.com/avatar/b68de5ae38616c296fa345d2b9df2225?d=https://a248.e.akamai.net/assets.github.com%2Fimages%2Fgravatars%2Fgravatar-140.png","id":327146,"public_gists":4,"login":"jacquev6"} diff --git a/github/Github.UnitTest.py b/github/Github.UnitTest.py deleted file mode 100644 index 73d75064..00000000 --- a/github/Github.UnitTest.py +++ /dev/null @@ -1,118 +0,0 @@ -import unittest -import MockMockMock - -from Github import Github - -class TestCase( unittest.TestCase ): - def setUp( self ): - unittest.TestCase.setUp( self ) - - self.requester = MockMockMock.Mock( "requester" ) - self.debugFile = MockMockMock.Mock( "debugFile", self.requester ) - - self.g = Github( "login", "password", self.debugFile.object ) - self.g._Github__requester = self.requester.object - - def tearDown( self ): - self.requester.tearDown() - unittest.TestCase.tearDown( self ) - - def testCreateForkForUser( self ): - self.requester.expect.dataRequest( "GET", "/users/xxx", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "POST", "/repos/xxx/yyy/forks", None, None ).andReturn( { "name": "yyy", "owner": { "login": "login" } } ) - self.g.get_user().create_fork( self.g.get_user( "xxx" ).get_repo( "yyy" ) ) - - def testCreateForkForOrganization( self ): - self.requester.expect.dataRequest( "GET", "/orgs/ooo", None, None ).andReturn( { "login": "ooo" } ) - self.requester.expect.dataRequest( "GET", "/users/xxx", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "POST", "/repos/xxx/yyy/forks", { "org": "ooo" }, None ).andReturn( { "name": "yyy", "owner": { "login": "ooo" } } ) - self.g.get_organization( "ooo" ).create_fork( self.g.get_user( "xxx" ).get_repo( "yyy" ) ) - - def testQueryFollowing( self ): - self.requester.expect.dataRequest( "GET", "/users/xxx", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.statusRequest( "GET", "/user/following/xxx", None, None ).andReturn( 404 ) - self.requester.expect.dataRequest( "GET", "/users/yyy", None, None ).andReturn( { "login": "yyy" } ) - self.requester.expect.statusRequest( "GET", "/user/following/yyy", None, None ).andReturn( 204 ) - self.assertFalse( self.g.get_user().has_in_following( self.g.get_user( "xxx" ) ) ) - self.assertTrue( self.g.get_user().has_in_following( self.g.get_user( "yyy" ) ) ) - - def testGist( self ): - self.requester.expect.dataRequest( "GET", "/gists/123456", None, None ).andReturn( { "description": "xxx" } ) - g = self.g.get_gist( 123456 ) - self.assertEqual( g.description, "xxx" ) - self.requester.expect.statusRequest( "GET", "/gists/123456/star", None, None ).andReturn( 404 ) - self.assertFalse( g.is_starred() ) - self.requester.expect.statusRequest( "PUT", "/gists/123456/star", None, None ).andReturn( 204 ) - g.set_starred() - self.requester.expect.statusRequest( "DELETE", "/gists/123456/star", None, None ).andReturn( 204 ) - g.reset_starred() - self.requester.expect.dataRequest( "POST", "/gists/123456/fork", None, None ).andReturn( { "description": "yyy" } ) - self.assertEqual( g.create_fork().description, "yyy" ) - self.requester.expect.dataRequest( "GET", "/gists/starred", None, None ).andReturn( [ { "description": "xxx" }, { "description": "yyy" } ] ) - self.assertEqual( len( self.g.get_user().get_starred_gists() ), 2 ) - - def testRepositoryReference( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - r = self.g.get_user().get_repo( "yyy" ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/milestones/1", None, None ).andReturn( { "number": 1 } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/milestones/1/labels", {}, None ).andReturn( [ { "name": "a" } ] ) - self.assertIs( r.get_milestone( 1 ).get_labels()[ 0 ]._repo, r ) - - def testHooks( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/hooks/1", None, None ).andReturn( { "name": "web", "id": 1 } ) - h = self.g.get_user().get_repo( "yyy" ).get_hook( 1 ) - self.requester.expect.statusRequest( "POST", "/repos/xxx/yyy/hooks/1/test", None, None ).andReturn( 204 ) - h.test() - - def testUserEvents( self ): - self.requester.expect.dataRequest( "GET", "/users/xxx", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/users/xxx/events/public", None, None ).andReturn( [] ) - self.requester.expect.dataRequest( "GET", "/users/xxx/received_events/public", None, None ).andReturn( [] ) - u = self.g.get_user( "xxx" ) - u.get_public_events() - u.get_public_received_events() - - def testRepoEvents( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "GET", "/networks/xxx/yyy/events", None, None ).andReturn( [] ) - r = self.g.get_user().get_repo( "yyy" ) - r.get_network_events() - - def testOrgEvents( self ): - self.requester.expect.dataRequest( "GET", "/orgs/ooo", None, None ).andReturn( { "login": "ooo" } ) - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/users/xxx/events/orgs/ooo", None, None ).andReturn( [] ) - u = self.g.get_user() - o = self.g.get_organization( "ooo" ) - u.get_organization_events( o ) - - def testMergePullRequest( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/pulls/42", None, None ).andReturn( { "number": 42 } ) - self.requester.expect.statusRequest( "GET", "/repos/xxx/yyy/pulls/42/merge", None, None ).andReturn( 404 ) - self.requester.expect.statusRequest( "PUT", "/repos/xxx/yyy/pulls/42/merge", None, {} ).andReturn( 204 ) - self.requester.expect.statusRequest( "GET", "/repos/xxx/yyy/pulls/42/merge", None, None ).andReturn( 204 ) - p = self.g.get_user().get_repo( "yyy" ).get_pull( 42 ) - self.assertFalse( p.is_merged() ) - p.merge() - self.assertTrue( p.is_merged() ) - - def testRepositoryCompare( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx" } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy", None, None ).andReturn( { "name": "yyy", "owner": { "login": "xxx" } } ) - self.requester.expect.dataRequest( "GET", "/repos/xxx/yyy/compare/foo...bar", None, None ).andReturn( { "gabu": "zomeuh" } ) - self.assertEqual( self.g.get_user().get_repo( "yyy" ).compare( "foo", "bar" ), { "gabu": "zomeuh" } ) - - def testDebugPrint( self ): - self.requester.expect.dataRequest( "GET", "/user", None, None ).andReturn( { "login": "xxx", "unknownAttribute": 42 } ) - self.debugFile.expect.write( "Missing definition of attribute unknownAttribute in class AuthenticatedUser\n" ) - self.g.get_user().location - -unittest.main() diff --git a/github/Requester.UnitTest.py b/github/Requester.UnitTest.py deleted file mode 100644 index 1901018b..00000000 --- a/github/Requester.UnitTest.py +++ /dev/null @@ -1,64 +0,0 @@ -import unittest -import MockMockMock -import httplib -import base64 - -from Requester import Requester, UnknownGithubObject - -class TestCase( unittest.TestCase ): - def setUp( self ): - unittest.TestCase.setUp( self ) - - self.r = Requester( "login", "password" ) - self.b64_userpass = base64.b64encode( "login:password" ) - self.b64_userpass = self.b64_userpass.replace( '\n', '' ) - - self.connectionFactory = MockMockMock.Mock( "httplib.HTTPSConnection" ) - self.connection = MockMockMock.Mock( "connection", self.connectionFactory ) - self.response = MockMockMock.Mock( "response", self.connectionFactory ) - - httplib.HTTPSConnection = self.connectionFactory.object - - def tearDown( self ): - self.connectionFactory.tearDown() - unittest.TestCase.tearDown( self ) - - def expect( self, verb, url, input, status, responseHeaders, output ): - self.connectionFactory.expect( "api.github.com", strict = True ).andReturn( self.connection.object ) - self.connection.expect.request( verb, url, input, { "Authorization" : "Basic " + self.b64_userpass } ) - self.connection.expect.getresponse().andReturn( self.response.object ) - self.response.expect.status.andReturn( status ) - self.response.expect.getheaders().andReturn( responseHeaders ) - self.response.expect.read().andReturn( output ) - self.connection.expect.close() - - def testSimpleStatus( self ): - self.expect( "GET", "/test", "null", 200, [], "" ) - self.assertEqual( self.r.statusRequest( "GET", "/test", None, None ), 200 ) - - def testSimpleData( self ): - self.expect( "GET", "/test", "null", 200, [], '{ "foo": "bar" }' ) - self.assertEqual( self.r.dataRequest( "GET", "/test", None, None ), { "foo" : "bar" } ) - - def testDataOnBadStatus( self ): - self.expect( "GET", "/test", "null", 404, [], '{ "foo": "bar" }' ) - with self.assertRaises( UnknownGithubObject ): - self.r.dataRequest( "GET", "/test", None, None ) - - def testDataWithParametersAndData( self ): - self.expect( "GET", "/test?tata=tutu&toto=titi", '{"xxx": 42}', 200, [], '{ "foo": "bar" }' ) - self.assertEqual( self.r.dataRequest( "GET", "/test", { "toto" : "titi", "tata" : "tutu" }, { "xxx" : 42 } ), { "foo" : "bar" } ) - - def testPagination( self ): - self.expect( "GET", "/test", 'null', 200, [ ( "link", "; next, xxx; last" ) ], '[ 1, 2 ]' ) - self.expect( "GET", "/test?page=2", 'null', 200, [ ( "link", "xxx; prev, xxx; first, ; next, xxx; last" ) ], '[ 3, 4 ]' ) - self.expect( "GET", "/test?page=3", 'null', 200, [ ( "link", "xxx; prev, xxx; first" ) ], '[ 5, 6 ]' ) - self.assertEqual( self.r.dataRequest( "GET", "/test", None, None ), [ 1, 2, 3, 4, 5, 6 ] ) - - def testPaginationObviouslyFinished( self ): - self.expect( "GET", "/test", 'null', 200, [ ( "link", "; next, xxx; last" ) ], '[ 1, 2 ]' ) - self.expect( "GET", "/test?page=2", 'null', 200, [ ( "link", "xxx; prev, xxx; first, ; next, xxx; last" ) ], '[ 3, 4 ]' ) - self.expect( "GET", "/test?page=3", 'null', 200, [ ( "link", "xxx; prev, xxx; first" ) ], '[]' ) - self.assertEqual( self.r.dataRequest( "GET", "/test", None, None ), [ 1, 2, 3, 4 ] ) - -unittest.main() diff --git a/run_tests.sh b/run_tests.sh index 9532bcaa..3e6e61a7 100644 --- a/run_tests.sh +++ b/run_tests.sh @@ -3,29 +3,10 @@ rm -f $(find -name "*.pyc") coverage erase +coverage run NewIntegrationTest.py -for f in $(find -name "*IntegrationTest.py") -do - coverage run --append $f - echo -done +echo "==============" +echo "|| Coverage ||" +echo "==============" -echo "=====================================================" -echo "|| Coverage of integration tests (for information) ||" -echo "=====================================================" coverage report -m --include=./* -echo - -coverage erase - -for f in $(find -name "*UnitTest.py") -do - coverage run --append $f --quiet - echo -done - -echo "============================================" -echo "|| Coverage of unit tests (shall be 100%) ||" -echo "============================================" -coverage report -m --include=./* -echo