From: Stefan F. <ste...@we...> - 2012-06-06 16:33:28
|
Erik & Brett: recently I have mailed that I would like to add a mock library to support testing. At that time I preferred JMock (mostly above EasyMock). However I did reevaluate my choice again and realized that the library that suited my tastes best is Mockito. see http://code.google.com/p/mockito/ Checkout the documentation at http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html which really shows very well the very simple but powerful style used. Or compare to the first test example which I have pushed to the rails2.0 branch (ActionChangeTest.java) in the junit folder with the identical hierachy as rails below (the source code itself is under src folder). It is really easy to create mock objects by simply annotate private fields in the test classes with @Mock or directly with Player player = mock(Player.class) Verifying that a method of the mock is called (once) requires: verify(mock).method() And stubbing a method of the mock is initialized with: when(mock.method()).thenReturn(value) Avoiding using strings also ensures that autocompletion of Eclipse-IDe still works. This syntactical sugar simplifies unit tests substantially (at least in my opinion). Stefan |
From: brett l. <bre...@gm...> - 2012-06-06 17:07:03
|
I have no objections to Mockito. One thing I'd like to see is just a central mocked data set that we can use for exercising the code. Eventually, it would be nice to grow our test case coverage. ---Brett. On Wed, Jun 6, 2012 at 12:33 PM, Stefan Frey <ste...@we...> wrote: > Erik & Brett: > recently I have mailed that I would like to add a mock library to > support testing. At that time I preferred JMock (mostly above EasyMock). > However I did reevaluate my choice again and realized that the library > that suited my tastes best is Mockito. > see http://code.google.com/p/mockito/ > > Checkout the documentation at > http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html > which really shows very well the very simple but powerful style used. > > Or compare to the first test example which I have pushed to the rails2.0 > branch (ActionChangeTest.java) in the junit folder with the identical > hierachy as rails below (the source code itself is under src folder). > > It is really easy to create mock objects by simply annotate private > fields in the test classes with @Mock > or directly with Player player = mock(Player.class) > > Verifying that a method of the mock is called (once) requires: > verify(mock).method() > > And stubbing a method of the mock is initialized with: > when(mock.method()).thenReturn(value) > > Avoiding using strings also ensures that autocompletion of Eclipse-IDe > still works. > > This syntactical sugar simplifies unit tests substantially (at least in > my opinion). > > Stefan > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Erik V. <eri...@xs...> - 2012-06-06 20:28:00
|
This all is way beyond my understanding, but if the two of you say that it's useful, I'm fine. Just wondering with what factor this will multiply the size of the Rails code. Erik. > -----Original Message----- > From: brett lentz [mailto:bre...@gm...] > Sent: Wednesday, June 06, 2012 7:07 PM > To: Development list for Rails: an 18xx game > Subject: Re: [Rails-devel] Mocking library chosen > > I have no objections to Mockito. > > One thing I'd like to see is just a central mocked data set that we can use for > exercising the code. Eventually, it would be nice to grow our test case > coverage. > > ---Brett. > > > On Wed, Jun 6, 2012 at 12:33 PM, Stefan Frey <ste...@we...> wrote: > > Erik & Brett: > > recently I have mailed that I would like to add a mock library to > > support testing. At that time I preferred JMock (mostly above EasyMock). > > However I did reevaluate my choice again and realized that the library > > that suited my tastes best is Mockito. > > see http://code.google.com/p/mockito/ > > > > Checkout the documentation at > > http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html > > which really shows very well the very simple but powerful style used. > > > > Or compare to the first test example which I have pushed to the > > rails2.0 branch (ActionChangeTest.java) in the junit folder with the > > identical hierachy as rails below (the source code itself is under src folder). > > > > It is really easy to create mock objects by simply annotate private > > fields in the test classes with @Mock or directly with Player player = > > mock(Player.class) > > > > Verifying that a method of the mock is called (once) requires: > > verify(mock).method() > > > > And stubbing a method of the mock is initialized with: > > when(mock.method()).thenReturn(value) > > > > Avoiding using strings also ensures that autocompletion of Eclipse-IDe > > still works. > > > > This syntactical sugar simplifies unit tests substantially (at least > > in my opinion). > > > > Stefan > > > > ---------------------------------------------------------------------- > > -------- > > Live Security Virtual Conference > > Exclusive live event will cover all the ways today's security and > > threat landscape has changed and how IT managers can respond. > > Discussions will include endpoint security, mobile security and the > > latest in malware threats. > > http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > > _______________________________________________ > > Rails-devel mailing list > > Rai...@li... > > https://lists.sourceforge.net/lists/listinfo/rails-devel > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and threat > landscape has changed and how IT managers can respond. Discussions will > include endpoint security, mobile security and the latest in malware threats. > http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: brett l. <bre...@gm...> - 2012-06-06 21:04:34
|
Typically, the test code and the application code are separate entities. Ideally, all tests and mocked objects should be off to the side in a 'test/' directory. This way, they are in the same repository, but can be removed from the released JARs and not cause unnecessary bloat. ---Brett. On Wed, Jun 6, 2012 at 4:27 PM, Erik Vos <eri...@xs...> wrote: > This all is way beyond my understanding, but if the two of you say that it's useful, I'm fine. > Just wondering with what factor this will multiply the size of the Rails code. > > Erik. > >> -----Original Message----- >> From: brett lentz [mailto:bre...@gm...] >> Sent: Wednesday, June 06, 2012 7:07 PM >> To: Development list for Rails: an 18xx game >> Subject: Re: [Rails-devel] Mocking library chosen >> >> I have no objections to Mockito. >> >> One thing I'd like to see is just a central mocked data set that we can use for >> exercising the code. Eventually, it would be nice to grow our test case >> coverage. >> >> ---Brett. >> >> >> On Wed, Jun 6, 2012 at 12:33 PM, Stefan Frey <ste...@we...> wrote: >> > Erik & Brett: >> > recently I have mailed that I would like to add a mock library to >> > support testing. At that time I preferred JMock (mostly above EasyMock). >> > However I did reevaluate my choice again and realized that the library >> > that suited my tastes best is Mockito. >> > see http://code.google.com/p/mockito/ >> > >> > Checkout the documentation at >> > http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html >> > which really shows very well the very simple but powerful style used. >> > >> > Or compare to the first test example which I have pushed to the >> > rails2.0 branch (ActionChangeTest.java) in the junit folder with the >> > identical hierachy as rails below (the source code itself is under src folder). >> > >> > It is really easy to create mock objects by simply annotate private >> > fields in the test classes with @Mock or directly with Player player = >> > mock(Player.class) >> > >> > Verifying that a method of the mock is called (once) requires: >> > verify(mock).method() >> > >> > And stubbing a method of the mock is initialized with: >> > when(mock.method()).thenReturn(value) >> > >> > Avoiding using strings also ensures that autocompletion of Eclipse-IDe >> > still works. >> > >> > This syntactical sugar simplifies unit tests substantially (at least >> > in my opinion). >> > >> > Stefan >> > >> > ---------------------------------------------------------------------- >> > -------- >> > Live Security Virtual Conference >> > Exclusive live event will cover all the ways today's security and >> > threat landscape has changed and how IT managers can respond. >> > Discussions will include endpoint security, mobile security and the >> > latest in malware threats. >> > http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >> > _______________________________________________ >> > Rails-devel mailing list >> > Rai...@li... >> > https://lists.sourceforge.net/lists/listinfo/rails-devel >> >> ------------------------------------------------------------------------------ >> Live Security Virtual Conference >> Exclusive live event will cover all the ways today's security and threat >> landscape has changed and how IT managers can respond. Discussions will >> include endpoint security, mobile security and the latest in malware threats. >> http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >> _______________________________________________ >> Rails-devel mailing list >> Rai...@li... >> https://lists.sourceforge.net/lists/listinfo/rails-devel > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Stefan F. <ste...@we...> - 2012-06-08 12:56:45
|
Brett and Erik: Some comments see below: * Test location: Yes as mentioned below in Rails 2.0 there are now two top-level directories: /src /junit where below src is all of the existing code and below junit everything for testing will be added. The hierarchy in junit will mirror that of src so that the tests are easy to find. * Code/Release size: Code size of Rails (below src) itself is not effected directly, but I hope to reduce the code by removing code duplication. However this will be easily offset by new functionality. The release size does not change as well as neither the test jars nor the test source is part of the release package. * Some more details for Erik: * Unit tests The main idea behind unit tests is that of "never change a running system". This is correct observation, however not changing a system is bad too, because this will easily lead to code duplication. So unit tests allow to "change a system, but keep it running". If you have automated tests that run before you changed the systems and after you changed the system, in fact you kept the system running, but you are still able to re-factor Another nice term I found for unit tests is "necessary waste": For perfect coders it is a waste of time, but as most of us are not of that kind, it is necessary. Actually unit testing and mocking is not that is not too difficult conceptually. Someone who got a graphical 1830 moderator working as you did, should have no problem to understand them. Unit testing itself mirrors the tests which are possible in an interpreted language: A) Write a function add(x,y) = x+y B) Call the function with foo(10, 15) in the console C) Check manually that the result is 25 and that no error was raised A unit test is: A) Write a function add(x,y) = x+y B) Write a test addTest(): assert(add(x,y),25) C) Start the test runner which reports passed if add(x,y) == 25 or fails if add(x,y) != 25 or returns an error. If you reverse A and B, thus you write the test before the actual code it is called TestDrivenDevelopment (TDD) * Mocks Usually you want to test classes as independent entities. And you want to configure setup the class to test alone. However often a method call requires or the construction of a class requires other objects. A mock library allows you to create a "phantom" object that pretends to be a object of the class, however actually does nothing at all. Example: If you create a Player mock using Player p = mock(Player.class) the variable p now can be passed as a player object and all methods of a player class can be called on p and everything compiles correctly. But in fact nothing happens if one calls methods on p. Or more precise nearly nothing happens: It is possible to ask the mock later if the methods got called. Assume that you test a function that adds a train to a player. It has two tasks: A) Add the train to the player B) Change the owner of the train to the player Now you can either create fully initialized player and train objects. However it might be easier to mock both player and train using Player p = mock(Player.class) and Train t = mock(Train.class) The function is called transferTrain(Player p, Train t). You pass both mocks to the function and then check that the function has called the according methods of player and train: verify(player).addTrain(t) verify(train).setOwner(p) Here it is easy to see why a test with fully initialized objects might be a little stronger: Then you would check that the train and player really have changed e.g. by assert(train.getOwner(),p), however this is would be already a joint test of both the function under test and the train object. There is a related technique called stubbing: In that case you not only create a phantom object, but more a skeleton object. A stub for a Player would be a minimal but working implementation. Mockito supports simple/basic stubbing as well: Assume that function would only succeed if the addTrain method of player returns a True value. This is possible by instructing the mock object to return that on a call of addTrain by: when(p.addTrain(t)).thenReturn(True) Feel free to ask more questions if you like. Stefan On 06/06/2012 11:04 PM, brett lentz wrote: > Typically, the test code and the application code are separate entities. > > Ideally, all tests and mocked objects should be off to the side in a > 'test/' directory. This way, they are in the same repository, but can > be removed from the released JARs and not cause unnecessary bloat. > > ---Brett. > > > On Wed, Jun 6, 2012 at 4:27 PM, Erik Vos<eri...@xs...> wrote: >> This all is way beyond my understanding, but if the two of you say that it's useful, I'm fine. >> Just wondering with what factor this will multiply the size of the Rails code. >> >> Erik. >> >>> -----Original Message----- >>> From: brett lentz [mailto:bre...@gm...] >>> Sent: Wednesday, June 06, 2012 7:07 PM >>> To: Development list for Rails: an 18xx game >>> Subject: Re: [Rails-devel] Mocking library chosen >>> >>> I have no objections to Mockito. >>> >>> One thing I'd like to see is just a central mocked data set that we can use for >>> exercising the code. Eventually, it would be nice to grow our test case >>> coverage. >>> >>> ---Brett. >>> >>> >>> On Wed, Jun 6, 2012 at 12:33 PM, Stefan Frey<ste...@we...> wrote: >>>> Erik& Brett: >>>> recently I have mailed that I would like to add a mock library to >>>> support testing. At that time I preferred JMock (mostly above EasyMock). >>>> However I did reevaluate my choice again and realized that the library >>>> that suited my tastes best is Mockito. >>>> see http://code.google.com/p/mockito/ >>>> >>>> Checkout the documentation at >>>> http://docs.mockito.googlecode.com/hg/latest/org/mockito/Mockito.html >>>> which really shows very well the very simple but powerful style used. >>>> >>>> Or compare to the first test example which I have pushed to the >>>> rails2.0 branch (ActionChangeTest.java) in the junit folder with the >>>> identical hierachy as rails below (the source code itself is under src folder). >>>> >>>> It is really easy to create mock objects by simply annotate private >>>> fields in the test classes with @Mock or directly with Player player = >>>> mock(Player.class) >>>> >>>> Verifying that a method of the mock is called (once) requires: >>>> verify(mock).method() >>>> >>>> And stubbing a method of the mock is initialized with: >>>> when(mock.method()).thenReturn(value) >>>> >>>> Avoiding using strings also ensures that autocompletion of Eclipse-IDe >>>> still works. >>>> >>>> This syntactical sugar simplifies unit tests substantially (at least >>>> in my opinion). >>>> >>>> Stefan >>>> >>>> ---------------------------------------------------------------------- >>>> -------- >>>> Live Security Virtual Conference >>>> Exclusive live event will cover all the ways today's security and >>>> threat landscape has changed and how IT managers can respond. >>>> Discussions will include endpoint security, mobile security and the >>>> latest in malware threats. >>>> http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>>> _______________________________________________ >>>> Rails-devel mailing list >>>> Rai...@li... >>>> https://lists.sourceforge.net/lists/listinfo/rails-devel >>> >>> ------------------------------------------------------------------------------ >>> Live Security Virtual Conference >>> Exclusive live event will cover all the ways today's security and threat >>> landscape has changed and how IT managers can respond. Discussions will >>> include endpoint security, mobile security and the latest in malware threats. >>> http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >>> _______________________________________________ >>> Rails-devel mailing list >>> Rai...@li... >>> https://lists.sourceforge.net/lists/listinfo/rails-devel >> >> >> ------------------------------------------------------------------------------ >> Live Security Virtual Conference >> Exclusive live event will cover all the ways today's security and >> threat landscape has changed and how IT managers can respond. Discussions >> will include endpoint security, mobile security and the latest in malware >> threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ >> _______________________________________________ >> Rails-devel mailing list >> Rai...@li... >> https://lists.sourceforge.net/lists/listinfo/rails-devel > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Erik V. <eri...@xs...> - 2012-06-08 14:12:22
|
Stefan, Thanks for your informational lecture. Unit testing is an old concept, of which I was well aware, but I have not really used it in practice throughout my professional life, and certainly not in an OO environment. Mocking and stubbing are new to me, but I understand their purpose now. The (superficial) impression I'm getting is that it is easy to test the things that are hard to get wrong, but a lot more difficult to test complex stuff that is easy to get wrong. For instance, how would you test that on a phase change a new train type does become available? Or does such a test already go beyond unit testing? Of course, a good design reduces the existence of such complexities as much as possible. But we all know that Rails has grown in a different way. Hopefully Rails 2.0 will improve that a great deal. Erik. > -----Original Message----- > From: Stefan Frey [mailto:ste...@we...] > Sent: Friday, June 08, 2012 2:56 PM > To: Development list for Rails: an 18xx game > Subject: Re: [Rails-devel] Mocking library chosen > > Brett and Erik: > > Some comments see below: > > * Test location: > Yes as mentioned below in Rails 2.0 there are now two top-level directories: > /src > /junit > > where below src is all of the existing code and below junit everything for > testing will be added. > > The hierarchy in junit will mirror that of src so that the tests are easy to find. > > * Code/Release size: > Code size of Rails (below src) itself is not effected directly, but I hope to > reduce the code by removing code duplication. However this will be easily > offset by new functionality. > > The release size does not change as well as neither the test jars nor the test > source is part of the release package. > > * Some more details for Erik: > > * Unit tests > The main idea behind unit tests is that of "never change a running system". > This is correct observation, however not changing a system is bad too, > because this will easily lead to code duplication. So unit tests allow to "change > a system, but keep it running". > If you have automated tests that run before you changed the systems and > after you changed the system, in fact you kept the system running, but you > are still able to re-factor > > Another nice term I found for unit tests is "necessary waste": > For perfect coders it is a waste of time, but as most of us are not of that kind, > it is necessary. > > Actually unit testing and mocking is not that is not too difficult conceptually. > Someone who got a graphical 1830 moderator working as you did, should > have no problem to understand them. > > Unit testing itself mirrors the tests which are possible in an interpreted > language: > A) Write a function add(x,y) = x+y > B) Call the function with foo(10, 15) in the console > C) Check manually that the result is 25 and that no error was raised > > A unit test is: > A) Write a function add(x,y) = x+y > B) Write a test addTest(): assert(add(x,y),25) > C) Start the test runner which reports passed if add(x,y) == 25 or fails if > add(x,y) != 25 or returns an error. > > If you reverse A and B, thus you write the test before the actual code it is > called TestDrivenDevelopment (TDD) > > * Mocks > Usually you want to test classes as independent entities. And you want to > configure setup the class to test alone. > > However often a method call requires or the construction of a class requires > other objects. > > A mock library allows you to create a "phantom" object that pretends to be a > object of the class, however actually does nothing at all. > > Example: > If you create a Player mock using > Player p = mock(Player.class) > the variable p now can be passed as a player object and all methods of a > player class can be called on p and everything compiles correctly. > But in fact nothing happens if one calls methods on p. > > Or more precise nearly nothing happens: > It is possible to ask the mock later if the methods got called. > > Assume that you test a function that adds a train to a player. It has two tasks: > A) Add the train to the player > B) Change the owner of the train to the player > > Now you can either create fully initialized player and train objects. > > However it might be easier to mock both player and train using Player p = > mock(Player.class) and Train t = mock(Train.class) > > The function is called transferTrain(Player p, Train t). > > You pass both mocks to the function and then check that the function has > called the according methods of player and train: > > verify(player).addTrain(t) > verify(train).setOwner(p) > > Here it is easy to see why a test with fully initialized objects might be a little > stronger: > Then you would check that the train and player really have changed e.g. > by assert(train.getOwner(),p), however this is would be already a joint test > of both the function under test and the train object. > > There is a related technique called stubbing: In that case you not only create > a phantom object, but more a skeleton object. A stub for a Player would be a > minimal but working implementation. > > Mockito supports simple/basic stubbing as well: Assume that function would > only succeed if the addTrain method of player returns a True value. This is > possible by instructing the mock object to return that on a call of addTrain by: > when(p.addTrain(t)).thenReturn(True) > > Feel free to ask more questions if you like. > > Stefan |
From: brett l. <bre...@gm...> - 2012-06-08 14:34:15
|
On Fri, Jun 8, 2012 at 10:12 AM, Erik Vos <eri...@xs...> wrote: > Stefan, > > Thanks for your informational lecture. Unit testing is an old concept, of > which I was well aware, but I have not really used it in practice > throughout my professional life, and certainly not in an OO environment. > Mocking and stubbing are new to me, but I understand their purpose now. > > The (superficial) impression I'm getting is that it is easy to test the > things that are hard to get wrong, but a lot more difficult to test complex > stuff that is easy to get wrong. > For instance, how would you test that on a phase change a new train type > does become available? Or does such a test already go beyond unit testing? > This is an area where it's important to have good OO design. The idea would be to mock/stub out dependencies of the Phase object, possibly all the way up to a mocked up GameManager. Then you'd instantiate a real Phase object (or set of Phase objects) with the mocked input data/objects. Finally, you'd call the sequence of methods that represents a phase change, and validate that the Phase object or the other appropriate mocked objects contain the data you expect. It's more complicated, and not everything is easy to mock or test, but sometimes just by going through the process of trying to test it you might realize that there's a change needed to the code that will make it more testable and less bug-prone. This extends into TDD where, by designing the test up front, you're spending time thinking through the design and the tests describe how you'd expect the code to operate. > Of course, a good design reduces the existence of such complexities as much > as possible. But we all know that Rails has grown in a different way. > Hopefully Rails 2.0 will improve that a great deal. > > Erik. > ---Brett. >> -----Original Message----- >> From: Stefan Frey [mailto:ste...@we...] >> Sent: Friday, June 08, 2012 2:56 PM >> To: Development list for Rails: an 18xx game >> Subject: Re: [Rails-devel] Mocking library chosen >> >> Brett and Erik: >> >> Some comments see below: >> >> * Test location: >> Yes as mentioned below in Rails 2.0 there are now two top-level > directories: >> /src >> /junit >> >> where below src is all of the existing code and below junit everything for >> testing will be added. >> >> The hierarchy in junit will mirror that of src so that the tests are easy > to find. >> >> * Code/Release size: >> Code size of Rails (below src) itself is not effected directly, but I hope > to >> reduce the code by removing code duplication. However this will be easily >> offset by new functionality. >> >> The release size does not change as well as neither the test jars nor the > test >> source is part of the release package. >> >> * Some more details for Erik: >> >> * Unit tests >> The main idea behind unit tests is that of "never change a running > system". >> This is correct observation, however not changing a system is bad too, >> because this will easily lead to code duplication. So unit tests allow to > "change >> a system, but keep it running". >> If you have automated tests that run before you changed the systems and >> after you changed the system, in fact you kept the system running, but you >> are still able to re-factor >> >> Another nice term I found for unit tests is "necessary waste": >> For perfect coders it is a waste of time, but as most of us are not of > that kind, >> it is necessary. >> >> Actually unit testing and mocking is not that is not too difficult > conceptually. >> Someone who got a graphical 1830 moderator working as you did, should >> have no problem to understand them. >> >> Unit testing itself mirrors the tests which are possible in an interpreted >> language: >> A) Write a function add(x,y) = x+y >> B) Call the function with foo(10, 15) in the console >> C) Check manually that the result is 25 and that no error was raised >> >> A unit test is: >> A) Write a function add(x,y) = x+y >> B) Write a test addTest(): assert(add(x,y),25) >> C) Start the test runner which reports passed if add(x,y) == 25 or fails > if >> add(x,y) != 25 or returns an error. >> >> If you reverse A and B, thus you write the test before the actual code it > is >> called TestDrivenDevelopment (TDD) >> >> * Mocks >> Usually you want to test classes as independent entities. And you want to >> configure setup the class to test alone. >> >> However often a method call requires or the construction of a class > requires >> other objects. >> >> A mock library allows you to create a "phantom" object that pretends to be > a >> object of the class, however actually does nothing at all. >> >> Example: >> If you create a Player mock using >> Player p = mock(Player.class) >> the variable p now can be passed as a player object and all methods of a >> player class can be called on p and everything compiles correctly. >> But in fact nothing happens if one calls methods on p. >> >> Or more precise nearly nothing happens: >> It is possible to ask the mock later if the methods got called. >> >> Assume that you test a function that adds a train to a player. It has two > tasks: >> A) Add the train to the player >> B) Change the owner of the train to the player >> >> Now you can either create fully initialized player and train objects. >> >> However it might be easier to mock both player and train using Player p = >> mock(Player.class) and Train t = mock(Train.class) >> >> The function is called transferTrain(Player p, Train t). >> >> You pass both mocks to the function and then check that the function has >> called the according methods of player and train: >> >> verify(player).addTrain(t) >> verify(train).setOwner(p) >> >> Here it is easy to see why a test with fully initialized objects might be > a little >> stronger: >> Then you would check that the train and player really have changed e.g. >> by assert(train.getOwner(),p), however this is would be already a joint > test >> of both the function under test and the train object. >> >> There is a related technique called stubbing: In that case you not only > create >> a phantom object, but more a skeleton object. A stub for a Player would be > a >> minimal but working implementation. >> >> Mockito supports simple/basic stubbing as well: Assume that function would >> only succeed if the addTrain method of player returns a True value. This > is >> possible by instructing the mock object to return that on a call of > addTrain by: >> when(p.addTrain(t)).thenReturn(True) >> >> Feel free to ask more questions if you like. >> >> Stefan > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Stefan F. <ste...@we...> - 2012-06-08 14:38:32
|
Erik, yes it is easy to create a lot of trivial test cases (e.g. testing getters and setters), so I usually will skip those. However sometimes e.g. the setter checks conditions or the getter itself does a calculation before returning, then it is worth testing. I am not a specialist in the subtleties of the definitions of various types of testing, but the scenario you mentioned below is in my opinion still unit testing. The more interesting question is how you setup the scenario: Do you try a simple realistic scenario where you have e.g. a fully defined TrainManager etc. or do you everything except the Phase object mocked? The first case is more difficult to setup, the latter is closer to being trivial (e.g. only testing that Phase is calling the TrainManager.releaseTrain() method, just guessing I do not know how it works in practice). The trade-off between complexity and trivial reminds me of the following anecdote: I had the pleasure to hear a lecture of a noble prize winner on a smaller conference shortly after the official ceremony where he got the price officially awarded. He was in a press conference where the journalists were asking him, oh could you please explain what your contribution was. So he simplified things a little bit, press people were still confused: A little simpler please. And he did that too, but this was not enough. In the end he was able to summarize things a few sentences. The next question then was: "How is it possible to get a noble prize with something that easy?" So my conclusion is: In a perfectly designed program everything appears to be trivial. Stefan On 06/08/2012 04:12 PM, Erik Vos wrote: > Stefan, > > Thanks for your informational lecture. Unit testing is an old concept, of > which I was well aware, but I have not really used it in practice > throughout my professional life, and certainly not in an OO environment. > Mocking and stubbing are new to me, but I understand their purpose now. > > The (superficial) impression I'm getting is that it is easy to test the > things that are hard to get wrong, but a lot more difficult to test complex > stuff that is easy to get wrong. > For instance, how would you test that on a phase change a new train type > does become available? Or does such a test already go beyond unit testing? > > Of course, a good design reduces the existence of such complexities as much > as possible. But we all know that Rails has grown in a different way. > Hopefully Rails 2.0 will improve that a great deal. > > Erik. > >> -----Original Message----- >> From: Stefan Frey [mailto:ste...@we...] >> Sent: Friday, June 08, 2012 2:56 PM >> To: Development list for Rails: an 18xx game >> Subject: Re: [Rails-devel] Mocking library chosen >> >> Brett and Erik: >> >> Some comments see below: >> >> * Test location: >> Yes as mentioned below in Rails 2.0 there are now two top-level > directories: >> /src >> /junit >> >> where below src is all of the existing code and below junit everything for >> testing will be added. >> >> The hierarchy in junit will mirror that of src so that the tests are easy > to find. >> >> * Code/Release size: >> Code size of Rails (below src) itself is not effected directly, but I hope > to >> reduce the code by removing code duplication. However this will be easily >> offset by new functionality. >> >> The release size does not change as well as neither the test jars nor the > test >> source is part of the release package. >> >> * Some more details for Erik: >> >> * Unit tests >> The main idea behind unit tests is that of "never change a running > system". >> This is correct observation, however not changing a system is bad too, >> because this will easily lead to code duplication. So unit tests allow to > "change >> a system, but keep it running". >> If you have automated tests that run before you changed the systems and >> after you changed the system, in fact you kept the system running, but you >> are still able to re-factor >> >> Another nice term I found for unit tests is "necessary waste": >> For perfect coders it is a waste of time, but as most of us are not of > that kind, >> it is necessary. >> >> Actually unit testing and mocking is not that is not too difficult > conceptually. >> Someone who got a graphical 1830 moderator working as you did, should >> have no problem to understand them. >> >> Unit testing itself mirrors the tests which are possible in an interpreted >> language: >> A) Write a function add(x,y) = x+y >> B) Call the function with foo(10, 15) in the console >> C) Check manually that the result is 25 and that no error was raised >> >> A unit test is: >> A) Write a function add(x,y) = x+y >> B) Write a test addTest(): assert(add(x,y),25) >> C) Start the test runner which reports passed if add(x,y) == 25 or fails > if >> add(x,y) != 25 or returns an error. >> >> If you reverse A and B, thus you write the test before the actual code it > is >> called TestDrivenDevelopment (TDD) >> >> * Mocks >> Usually you want to test classes as independent entities. And you want to >> configure setup the class to test alone. >> >> However often a method call requires or the construction of a class > requires >> other objects. >> >> A mock library allows you to create a "phantom" object that pretends to be > a >> object of the class, however actually does nothing at all. >> >> Example: >> If you create a Player mock using >> Player p = mock(Player.class) >> the variable p now can be passed as a player object and all methods of a >> player class can be called on p and everything compiles correctly. >> But in fact nothing happens if one calls methods on p. >> >> Or more precise nearly nothing happens: >> It is possible to ask the mock later if the methods got called. >> >> Assume that you test a function that adds a train to a player. It has two > tasks: >> A) Add the train to the player >> B) Change the owner of the train to the player >> >> Now you can either create fully initialized player and train objects. >> >> However it might be easier to mock both player and train using Player p = >> mock(Player.class) and Train t = mock(Train.class) >> >> The function is called transferTrain(Player p, Train t). >> >> You pass both mocks to the function and then check that the function has >> called the according methods of player and train: >> >> verify(player).addTrain(t) >> verify(train).setOwner(p) >> >> Here it is easy to see why a test with fully initialized objects might be > a little >> stronger: >> Then you would check that the train and player really have changed e.g. >> by assert(train.getOwner(),p), however this is would be already a joint > test >> of both the function under test and the train object. >> >> There is a related technique called stubbing: In that case you not only > create >> a phantom object, but more a skeleton object. A stub for a Player would be > a >> minimal but working implementation. >> >> Mockito supports simple/basic stubbing as well: Assume that function would >> only succeed if the addTrain method of player returns a True value. This > is >> possible by instructing the mock object to return that on a call of > addTrain by: >> when(p.addTrain(t)).thenReturn(True) >> >> Feel free to ask more questions if you like. >> >> Stefan > > > ------------------------------------------------------------------------------ > Live Security Virtual Conference > Exclusive live event will cover all the ways today's security and > threat landscape has changed and how IT managers can respond. Discussions > will include endpoint security, mobile security and the latest in malware > threats. http://www.accelacomm.com/jaw/sfrnl04242012/114/50122263/ > _______________________________________________ > Rails-devel mailing list > Rai...@li... > https://lists.sourceforge.net/lists/listinfo/rails-devel |
From: Erik V. <eri...@xs...> - 2012-06-08 14:51:13
|
> So my conclusion is: In a perfectly designed program everything appears to > be trivial. That's indeed the most important quality of a good design. The big problem is: how to get there. But that's another story (or perhaps not). Erik. |