On Thu, Jul 26, 2012 at 08:46:26PM -0000, Gary Lasker wrote:
> This is targeted for trunk only currently as it includes a new string.
[..]
Thanks for the update of this branch to trunk.
I reviewed this in detail now. Its a bit of a long reply, I'm sorry
for that. Pleae note that there is nothing wrong with the branch, it
can land as it is. It got a bit long because of various ideas I had
while reading the code and the diff and I wanted to share them. All of
this can be done in future branches if you prefer to land this as it
is. Please also note that those are suggestions, its fine to not agree
with them :)
The config parser has a "getboolean" method that can be used here, it
will automatically convert from various strings and you can simply
return the value of it which should make this easier.
[..]
> === modified file 'tests/gtk3/test_catview.py'
> --- tests/gtk3/test_catview.py 2012-07-13 07:39:30 +0000
> +++ tests/gtk3/test_catview.py 2012-07-26 20:45:23 +0000
> @@ -33,8 +33,17 @@
> def setUpClass(cls):
> cls.db = get_test_db()
>
> - def setUp(self):
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.get_sso_backend')
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
> + '.is_opted_in')
> + # patch out the agent query method to avoid making the actual server call
> + @patch('softwarecenter.ui.gtk3.widgets.recommendations.RecommenderAgent'
> + '.post_submit_profile')
> + def setUp(self, mock_query, mock_recommender_is_opted_in, mock_sso):
> self._cat = None
> + # patch the recommender to specify that we are not opted-in at
> + # the start of each test
> + mock_recommender_is_opted_in.return_value = False
> self.win = get_test_window_catview(self.db)
> self.addCleanup(self.win.destroy)
> self.notebook = self.win.get_child()
I really like moving the patch decoratos from the individual tests to
the setUp() function, I think that is a nice change, I wonder if this
is the best place though. This is adding the patches to the
CaViewBaseTestCase which is used for various other testcases that are
unreleated to the recommendations functionatlity. Would it be possible
to move this into a more targeted setUp() call like
RecommendationstestCase ? E.g. something like
> -
> + def test_recommended_for_you_display_recommendations_opted_in(self):
> + # click the opt-in button to initiate the process,
> + # this will show the spinner
> + self.rec_panel.opt_in_button.emit('clicked')
> + do_events()
> + self.rec_panel._update_recommended_for_you_content()
> + do_events()
[..]
Unreleated to this branch I noticed that
test_recommended_for_you_display_recommendations_opted_in()
and
test_recommended_for_you_display_recommendations()
share the same "make a fake callback from the agent" code, its not
much but I wonder if it would make sense to move it into a small
helper that just takes different top-level rec_panel or rec_cat_panel?
Might be a nice way of extracting some common code as the two tests
look similar in some ways.
Some other random thoughts:
- could we simply assume that if there is a uuid generated, that
means that the user requested a opt-in? or is the seperate
recommender_opt_in_requested config needed (e.g. to make things
simpler)? like just generate the uuid on opt-in?
More random random thoughts:
- I wonder if the "recommendations-opt-{in,out}" signals would be
better placed in the RecommendationsAgent? E.g. functions there
like "opt_{in,out}" that do the magic and sends the signals. The
reason it occured to me is that then we would have a "star topology"
with the RecommenerAgent in the middle where e.g. the menu in
app.py does not have to know anything about the
RecommendationsPanelLobby (nicer seperation between GUI and
backend), just about the RecommenderAgent (which it
does already). The RecommendationsPanelLobby would now just have to
subscript to the signals instead of sending them itself.
On Thu, Jul 26, 2012 at 08:46:26PM -0000, Gary Lasker wrote:
> This is targeted for trunk only currently as it includes a new string.
[..]
Thanks for the update of this branch to trunk.
I reviewed this in detail now. Its a bit of a long reply, I'm sorry
for that. Pleae note that there is nothing wrong with the branch, it
can land as it is. It got a bit long because of various ideas I had
while reading the code and the diff and I wanted to share them. All of
this can be done in future branches if you prefer to land this as it
is. Please also note that those are suggestions, its fine to not agree
with them :)
Some comments inline:
> === modified file 'softwarecenter /backend/ recagent. py' backend/ recagent. py 2012-04-02 18:23:20 +0000 backend/ recagent. py 2012-07-26 20:45:23 +0000 md5(str( profile) ).hexdigest( ) requested( self): has_option( "general" , "recommender_ opt_in_ requested" ): get("general" , opt_in_ requested" )
> --- softwarecenter/
> +++ softwarecenter/
> @@ -95,6 +95,15 @@
> return hashlib.
>
> @property
> + def opt_in_
> + if self.config.
> + opt_in_requested = self.config.
> + "recommender_
> + if opt_in_requested == "True":
> + return True
[..]
The config parser has a "getboolean" method that can be used here, it
will automatically convert from various strings and you can simply
return the value of it which should make this easier.
> + def recommender_ opt_in_ requested( self, opt_in_requested): set("general" , opt_in_ requested" , set("general" , opt_in_ requested" ,
> + if opt_in_requested:
> + self.config.
> + "recommender_
> + "True")
> + else:
> + self.config.
> + "recommender_
> + "False")
If we are sure we awlays gets booleans from opt_in_requested, then
this could probably be written in a more compat form as:
(not that it matter much :).
[..] gtk3/test_ catview. py' test_catview. py 2012-07-13 07:39:30 +0000 test_catview. py 2012-07-26 20:45:23 +0000 'softwarecenter .ui.gtk3. widgets. recommendations .get_sso_ backend' ) 'softwarecenter .ui.gtk3. widgets. recommendations .RecommenderAge nt' 'softwarecenter .ui.gtk3. widgets. recommendations .RecommenderAge nt' submit_ profile' ) r_is_opted_ in, mock_sso): r_is_opted_ in.return_ value = False window_ catview( self.db) (self.win. destroy) get_child( )
> === modified file 'tests/
> --- tests/gtk3/
> +++ tests/gtk3/
> @@ -33,8 +33,17 @@
> def setUpClass(cls):
> cls.db = get_test_db()
>
> - def setUp(self):
> + @patch(
> + @patch(
> + '.is_opted_in')
> + # patch out the agent query method to avoid making the actual server call
> + @patch(
> + '.post_
> + def setUp(self, mock_query, mock_recommende
> self._cat = None
> + # patch the recommender to specify that we are not opted-in at
> + # the start of each test
> + mock_recommende
> self.win = get_test_
> self.addCleanup
> self.notebook = self.win.
I really like moving the patch decoratos from the individual tests to testCase ? E.g. something like
the setUp() function, I think that is a nice change, I wonder if this
is the best place though. This is adding the patches to the
CaViewBaseTestCase which is used for various other testcases that are
unreleated to the recommendations functionatlity. Would it be possible
to move this into a more targeted setUp() call like
Recommendations
class Recommendations testCase( )
@patch1
mock_1. return_ value ="what is needed"
super( Recommendations testCase, self).__init__()
@patch2
@pach3
def setUp(self, mock_1, mock_2, mock_3):
...
so that its more isolated?
> self.rec_ panel.opt_ in_button. emit('clicked' )
This could also be written as button.clicked() (not that it matters :)
> + @patch( 'softwarecenter .ui.gtk3. widgets. recommendations ' state_is_ connected' ) d_for_you_ network_ not_available( self, state_is_ connected) :
> + '.network_
> + def test_recommende
> + mock_network_
[..]
Very nice, I really like this test!
> - d_for_you_ display_ recommendations _opted_ in(self) : panel.opt_ in_button. emit('clicked' ) panel._ update_ recommended_ for_you_ content( )
> + def test_recommende
> + # click the opt-in button to initiate the process,
> + # this will show the spinner
> + self.rec_
> + do_events()
> + self.rec_
> + do_events()
[..]
Unreleated to this branch I noticed that recommended_ for_you_ display_ recommendations _opted_ in() recommended_ for_you_ display_ recommendations ()
test_
and
test_
share the same "make a fake callback from the agent" code, its not
much but I wonder if it would make sense to move it into a small
helper that just takes different top-level rec_panel or rec_cat_panel?
Might be a nice way of extracting some common code as the two tests
look similar in some ways.
Some other random thoughts: opt_in_ requested config needed (e.g. to make things
- could we simply assume that if there is a uuid generated, that
means that the user requested a opt-in? or is the seperate
recommender_
simpler)? like just generate the uuid on opt-in?
More random random thoughts: s-opt-{ in,out} " signals would be Agent? E.g. functions there nsPanelLobby (nicer seperation between GUI and PanelLobby would now just have to
- I wonder if the "recommendation
better placed in the Recommendations
like "opt_{in,out}" that do the magic and sends the signals. The
reason it occured to me is that then we would have a "star topology"
with the RecommenerAgent in the middle where e.g. the menu in
app.py does not have to know anything about the
Recommendatio
backend), just about the RecommenderAgent (which it
does already). The Recommendations
subscript to the signals instead of sending them itself.
Cheers,
Michael