I am, as usual, assigning an instance variable in a controller''s index action to find all instances of a model in the database. I want to write a spec that checks that this variable is assigned correctly. I can do: it "should provide a collection of widgets in @widgets" do widget = Widget.create("title" => "my widget") get :index assigns[:widgets].should include(widget) end or: it "should provide a collection of widgets in @widgets" do widget = Factory.create(:widget) get :index assigns[:widgets].should include(widget) end Is there a better way to do this with a mock model, though? Thanks, Brennon Bortz Software Researcher Dundalk Institute of Technology brennon.bortz at casala.ie Ph.D. Researcher & Composer - Sonic Arts Research Centre Queen''s University, Belfast brennon at brennonbortz.com / bbortz01 at qub.ac.uk -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100830/f131fdac/attachment-0001.html>
On Aug 30, 11:59?am, Brennon Bortz <bren... at brennonbortz.com> wrote:> I am, as usual, assigning an instance variable in a controller''s index action to find all instances of a model in the database. ?I want to write a spec that checks that this variable is assigned correctly. ?I can do: > > it "should provide a collection of widgets in @widgets" do > ? ? ? widget = Widget.create("title" => "my widget") > ? ? ? get :index > ? ? ? assigns[:widgets].should include(widget) > end > > or: > > it "should provide a collection of widgets in @widgets" do > ? ? ? widget = Factory.create(:widget) > ? ? ? get :index > ? ? ? assigns[:widgets].should include(widget) > end > > Is there a better way to do this with a mock model, though? > > Thanks, > > Brennon Bortz > Software Researcher > Dundalk Institute of Technology > brennon.bo... at casala.ie > Ph.D. Researcher & Composer - Sonic Arts Research Centre > Queen''s University, Belfast > bren... at brennonbortz.com / bbort... at qub.ac.uk > > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-usersCurrently, what you''re doing is checking that the Widget model returns the correct widgets. If you want to isolate your controller spec from the model, you must stub or mock the model method call in the action. Example: it "..." do widget = mock_model(Widget) Widget.should_receive(:all).and_return([widget]) get :index assigns[:widgets].should include(widget) end To check that Widget.all does indeed return the correct widgets, I would spec that behaviour in the Widget model spec. Hope that helps.
On 30 Aug 2010, at 17:17, Justin Ko wrote:> > > On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: >> I am, as usual, assigning an instance variable in a controller''s index action to find all instances of a model in the database. I want to write a spec that checks that this variable is assigned correctly. I can do: >> >> it "should provide a collection of widgets in @widgets" do >> widget = Widget.create("title" => "my widget") >> get :index >> assigns[:widgets].should include(widget) >> end >> >> or: >> >> it "should provide a collection of widgets in @widgets" do >> widget = Factory.create(:widget) >> get :index >> assigns[:widgets].should include(widget) >> end >> >> Is there a better way to do this with a mock model, though? >> >> Thanks, >> >> Brennon Bortz >> Software Researcher >> Dundalk Institute of Technology >> brennon.bo... at casala.ie >> Ph.D. Researcher & Composer - Sonic Arts Research Centre >> Queen''s University, Belfast >> bren... at brennonbortz.com / bbort... at qub.ac.uk >> >> _______________________________________________ >> rspec-users mailing list >> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > Currently, what you''re doing is checking that the Widget model returns > the correct widgets. If you want to isolate your controller spec from > the model, you must stub or mock the model method call in the action. > Example: > > it "..." do > widget = mock_model(Widget) > Widget.should_receive(:all).and_return([widget]) > get :index > assigns[:widgets].should include(widget) > end > > To check that Widget.all does indeed return the correct widgets, I > would spec that behaviour in the Widget model spec. > > Hope that helps.Hrm...that''s exactly what I''d started with, and I was getting the following error: Failures: 1) WidgetsController GET ''index'' should provide a collection of widgets in @widgets Failure/Error: assigns[:widgets].should include(widget) expected [] to include #<Widget:0x81686290 @name="Widget_1001"> Stupidly, I had defined my controller method as: def index @widgets = Widget.find(:all) end Changed that assignment to Widget.all...problem solved.
On Aug 30, 12:54?pm, Brennon Bortz <bren... at brennonbortz.com> wrote:> On 30 Aug 2010, at 17:17, Justin Ko wrote: > > > > > > > > > On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: > >> I am, as usual, assigning an instance variable in a controller''s index action to find all instances of a model in the database. ?I want to write a spec that checks that this variable is assigned correctly. ?I can do: > > >> it "should provide a collection of widgets in @widgets" do > >> ? ? ? widget = Widget.create("title" => "my widget") > >> ? ? ? get :index > >> ? ? ? assigns[:widgets].should include(widget) > >> end > > >> or: > > >> it "should provide a collection of widgets in @widgets" do > >> ? ? ? widget = Factory.create(:widget) > >> ? ? ? get :index > >> ? ? ? assigns[:widgets].should include(widget) > >> end > > >> Is there a better way to do this with a mock model, though? > > >> Thanks, > > >> Brennon Bortz > >> Software Researcher > >> Dundalk Institute of Technology > >> brennon.bo... at casala.ie > >> Ph.D. Researcher & Composer - Sonic Arts Research Centre > >> Queen''s University, Belfast > >> bren... at brennonbortz.com / bbort... at qub.ac.uk > > >> _______________________________________________ > >> rspec-users mailing list > >> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > > Currently, what you''re doing is checking that the Widget model returns > > the correct widgets. If you want to isolate your controller spec from > > the model, you must stub or mock the model method call in the action. > > Example: > > > it "..." do > > ?widget = mock_model(Widget) > > ?Widget.should_receive(:all).and_return([widget]) > > ?get :index > > ?assigns[:widgets].should include(widget) > > end > > > To check that Widget.all does indeed return the correct widgets, I > > would spec that behaviour in the Widget model spec. > > > Hope that helps. > > Hrm...that''s exactly what I''d started with, and I was getting the following error: > > Failures: > ? 1) WidgetsController GET ''index'' should provide a collection of widgets in @widgets > ? ? ?Failure/Error: assigns[:widgets].should include(widget) > ? ? ?expected [] to include #<Widget:0x81686290 @name="Widget_1001"> > > Stupidly, I had defined my controller method as: > > def index > ? @widgets = Widget.find(:all) > end > > Changed that assignment to Widget.all...problem solved. > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-usersTo mock a method that receives an argument, you can use the "with" method. Example: Widget.should_receive(:find).with(:all).and_return([widget]) Glad you got things fixed :)
On Aug 30, 2010, at 12:54 PM, Brennon Bortz wrote:> On 30 Aug 2010, at 17:17, Justin Ko wrote: >> On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: >>> I am, as usual, assigning an instance variable in a controller''s >>> index action to find all instances of a model in the database. I >>> want to write a spec that checks that this variable is assigned >>> correctly. I can do: >>> >>> it "should provide a collection of widgets in @widgets" do >>> widget = Widget.create("title" => "my widget") >>> get :index >>> assigns[:widgets].should include(widget) >>> end >>> >>> or: >>> >>> it "should provide a collection of widgets in @widgets" do >>> widget = Factory.create(:widget) >>> get :index >>> assigns[:widgets].should include(widget) >>> end >>> >>> Is there a better way to do this with a mock model, though? >>> >>> Thanks, >>> >>> Brennon Bortz >>> Software Researcher >>> Dundalk Institute of Technology >>> brennon.bo... at casala.ie >>> Ph.D. Researcher & Composer - Sonic Arts Research Centre >>> Queen''s University, Belfast >>> bren... at brennonbortz.com / bbort... at qub.ac.uk >>> >>> _______________________________________________ >>> rspec-users mailing list >>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users >> >> Currently, what you''re doing is checking that the Widget model >> returns >> the correct widgets. If you want to isolate your controller spec from >> the model, you must stub or mock the model method call in the action. >> Example: >> >> it "..." do >> widget = mock_model(Widget) >> Widget.should_receive(:all).and_return([widget]) >> get :index >> assigns[:widgets].should include(widget) >> end >> >> To check that Widget.all does indeed return the correct widgets, I >> would spec that behaviour in the Widget model spec. >> >> Hope that helps. > > Hrm...that''s exactly what I''d started with, and I was getting the > following error: > > Failures: > 1) WidgetsController GET ''index'' should provide a collection of > widgets in @widgets > Failure/Error: assigns[:widgets].should include(widget) > expected [] to include #<Widget:0x81686290 @name="Widget_1001"> > > Stupidly, I had defined my controller method as: > > def index > @widgets = Widget.find(:all) > end > > Changed that assignment to Widget.all...problem solved.And THAT is the problem with using mocks (or stubs) for this. You run the very real risk of specifying the implementation details in the structure of the spec/test. There is a problem when you''ve limited the refactoring that can be done without altering the spec/test. Since Widget.find(:all) and Widget.all should always have the same result, the mere presence of the mock has cut off one possible refactoring. (The one that I distaste most limits changing .find(params[:id]) to .find_by_id(params[:id]) by mocking/stubbing the call to find.) Think about what really needs to be specified and be careful to mock/ stub as little as possible and to do so in a way that will limit opportunities to refactor the least. -Rob Rob Biedenharn Rob at AgileConsultingLLC.com http://AgileConsultingLLC.com/ rab at GaslightSoftware.com http://GaslightSoftware.com/
On Aug 30, 1:09?pm, Rob Biedenharn <R... at AgileConsultingLLC.com> wrote:> On Aug 30, 2010, at 12:54 PM, Brennon Bortz wrote: > > > > > > > On 30 Aug 2010, at 17:17, Justin Ko wrote: > >> On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: > >>> I am, as usual, assigning an instance variable in a controller''s ? > >>> index action to find all instances of a model in the database. ?I ? > >>> want to write a spec that checks that this variable is assigned ? > >>> correctly. ?I can do: > > >>> it "should provide a collection of widgets in @widgets" do > >>> ? ? ?widget = Widget.create("title" => "my widget") > >>> ? ? ?get :index > >>> ? ? ?assigns[:widgets].should include(widget) > >>> end > > >>> or: > > >>> it "should provide a collection of widgets in @widgets" do > >>> ? ? ?widget = Factory.create(:widget) > >>> ? ? ?get :index > >>> ? ? ?assigns[:widgets].should include(widget) > >>> end > > >>> Is there a better way to do this with a mock model, though? > > >>> Thanks, > > >>> Brennon Bortz > >>> Software Researcher > >>> Dundalk Institute of Technology > >>> brennon.bo... at casala.ie > >>> Ph.D. Researcher & Composer - Sonic Arts Research Centre > >>> Queen''s University, Belfast > >>> bren... at brennonbortz.com / bbort... at qub.ac.uk > > >>> _______________________________________________ > >>> rspec-users mailing list > >>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > >> Currently, what you''re doing is checking that the Widget model ? > >> returns > >> the correct widgets. If you want to isolate your controller spec from > >> the model, you must stub or mock the model method call in the action. > >> Example: > > >> it "..." do > >> widget = mock_model(Widget) > >> Widget.should_receive(:all).and_return([widget]) > >> get :index > >> assigns[:widgets].should include(widget) > >> end > > >> To check that Widget.all does indeed return the correct widgets, I > >> would spec that behaviour in the Widget model spec. > > >> Hope that helps. > > > Hrm...that''s exactly what I''d started with, and I was getting the ? > > following error: > > > Failures: > > ?1) WidgetsController GET ''index'' should provide a collection of ? > > widgets in @widgets > > ? ? Failure/Error: assigns[:widgets].should include(widget) > > ? ? expected [] to include #<Widget:0x81686290 @name="Widget_1001"> > > > Stupidly, I had defined my controller method as: > > > def index > > ?@widgets = Widget.find(:all) > > end > > > Changed that assignment to Widget.all...problem solved. > > And THAT is the problem with using mocks (or stubs) for this. ?You run ? > the very real risk of specifying the implementation details in the ? > structure of the spec/test. ?There is a problem when you''ve limited ? > the refactoring that can be done without altering the spec/test. Since ? > Widget.find(:all) and Widget.all should always have the same result, ? > the mere presence of the mock has cut off one possible refactoring. ? > (The one that I distaste most limits changing .find(params[:id]) ? > to .find_by_id(params[:id]) by mocking/stubbing the call to find.) > > Think about what really needs to be specified and be careful to mock/ > stub as little as possible and to do so in a way that will limit ? > opportunities to refactor the least. > > -Rob > > Rob Biedenharn ? ? ? ? ? > R... at AgileConsultingLLC.com ?http://AgileConsultingLLC.com/ > r... at GaslightSoftware.com ? ? ? ? ? ?http://GaslightSoftware.com/ > > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-usersThe method you suggested does benefit refactoring. However, by not stubbing or mocking, your controller is no longer in isolation. Which means if Widget.all breaks, the model AND controller spec will fail. The are pros and cons to both ways. But what has pushed me to the isolation side is that without mocking/stubbing, you must create a record in the database (via fixtures or factories) and it is much slower.
On Aug 30, 1:32?pm, Justin Ko <jko... at gmail.com> wrote:> On Aug 30, 1:09?pm, Rob Biedenharn <R... at AgileConsultingLLC.com> > wrote: > > > > > > > On Aug 30, 2010, at 12:54 PM, Brennon Bortz wrote: > > > > On 30 Aug 2010, at 17:17, Justin Ko wrote: > > >> On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: > > >>> I am, as usual, assigning an instance variable in a controller''s ? > > >>> index action to find all instances of a model in the database. ?I ? > > >>> want to write a spec that checks that this variable is assigned ? > > >>> correctly. ?I can do: > > > >>> it "should provide a collection of widgets in @widgets" do > > >>> ? ? ?widget = Widget.create("title" => "my widget") > > >>> ? ? ?get :index > > >>> ? ? ?assigns[:widgets].should include(widget) > > >>> end > > > >>> or: > > > >>> it "should provide a collection of widgets in @widgets" do > > >>> ? ? ?widget = Factory.create(:widget) > > >>> ? ? ?get :index > > >>> ? ? ?assigns[:widgets].should include(widget) > > >>> end > > > >>> Is there a better way to do this with a mock model, though? > > > >>> Thanks, > > > >>> Brennon Bortz > > >>> Software Researcher > > >>> Dundalk Institute of Technology > > >>> brennon.bo... at casala.ie > > >>> Ph.D. Researcher & Composer - Sonic Arts Research Centre > > >>> Queen''s University, Belfast > > >>> bren... at brennonbortz.com / bbort... at qub.ac.uk > > > >>> _______________________________________________ > > >>> rspec-users mailing list > > >>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > > >> Currently, what you''re doing is checking that the Widget model ? > > >> returns > > >> the correct widgets. If you want to isolate your controller spec from > > >> the model, you must stub or mock the model method call in the action. > > >> Example: > > > >> it "..." do > > >> widget = mock_model(Widget) > > >> Widget.should_receive(:all).and_return([widget]) > > >> get :index > > >> assigns[:widgets].should include(widget) > > >> end > > > >> To check that Widget.all does indeed return the correct widgets, I > > >> would spec that behaviour in the Widget model spec. > > > >> Hope that helps. > > > > Hrm...that''s exactly what I''d started with, and I was getting the ? > > > following error: > > > > Failures: > > > ?1) WidgetsController GET ''index'' should provide a collection of ? > > > widgets in @widgets > > > ? ? Failure/Error: assigns[:widgets].should include(widget) > > > ? ? expected [] to include #<Widget:0x81686290 @name="Widget_1001"> > > > > Stupidly, I had defined my controller method as: > > > > def index > > > ?@widgets = Widget.find(:all) > > > end > > > > Changed that assignment to Widget.all...problem solved. > > > And THAT is the problem with using mocks (or stubs) for this. ?You run ? > > the very real risk of specifying the implementation details in the ? > > structure of the spec/test. ?There is a problem when you''ve limited ? > > the refactoring that can be done without altering the spec/test. Since ? > > Widget.find(:all) and Widget.all should always have the same result, ? > > the mere presence of the mock has cut off one possible refactoring. ? > > (The one that I distaste most limits changing .find(params[:id]) ? > > to .find_by_id(params[:id]) by mocking/stubbing the call to find.) > > > Think about what really needs to be specified and be careful to mock/ > > stub as little as possible and to do so in a way that will limit ? > > opportunities to refactor the least. > > > -Rob > > > Rob Biedenharn ? ? ? ? ? > > R... at AgileConsultingLLC.com ?http://AgileConsultingLLC.com/ > > r... at GaslightSoftware.com ? ? ? ? ? ?http://GaslightSoftware.com/ > > > _______________________________________________ > > rspec-users mailing list > > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > The method you suggested does benefit refactoring. However, by not > stubbing or mocking, your controller is no longer in isolation. Which > means if Widget.all breaks, the model AND controller spec will fail. > > The are pros and cons to both ways. But what has pushed me to the > isolation side is that without mocking/stubbing, you must create a > record in the database (via fixtures or factories) and it is much > slower. > _______________________________________________ > rspec-users mailing list > rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-usersJust remembered another reason why I chose isolation. Sometimes, the setup to NOT isolate can be a real pain. a.k.a creating factories and relationships. But, let''s say you''ve something like this in your controller: User.where(:email => ''test at blah.com'').includes(:widgets).order(''users.email ASC'').limit(3) Simply stubbing or mocking that out would not spec the SQL very well. So what I usually do is extract it to the model: User.widgets_by_email(''test at blah.com'') # in model def self.widgets_by_email(email) where(:email => email).includes(:widgets).order(''users.email ASC'').limit(3) end After doing that, I feel comfortable mocking out "User.widgets_by_email" in the controller, because all I care about is if its called or not. And of course, since the method has been moved to the model, you can unit spec the hell out of it :)
On 30 Aug 2010, at 18:32, Justin Ko wrote:> > > On Aug 30, 1:09 pm, Rob Biedenharn <R... at AgileConsultingLLC.com> > wrote: >> On Aug 30, 2010, at 12:54 PM, Brennon Bortz wrote: >> >> >> >> >> >>> On 30 Aug 2010, at 17:17, Justin Ko wrote: >>>> On Aug 30, 11:59 am, Brennon Bortz <bren... at brennonbortz.com> wrote: >>>>> I am, as usual, assigning an instance variable in a controller''s >>>>> index action to find all instances of a model in the database. I >>>>> want to write a spec that checks that this variable is assigned >>>>> correctly. I can do: >> >>>>> it "should provide a collection of widgets in @widgets" do >>>>> widget = Widget.create("title" => "my widget") >>>>> get :index >>>>> assigns[:widgets].should include(widget) >>>>> end >> >>>>> or: >> >>>>> it "should provide a collection of widgets in @widgets" do >>>>> widget = Factory.create(:widget) >>>>> get :index >>>>> assigns[:widgets].should include(widget) >>>>> end >> >>>>> Is there a better way to do this with a mock model, though? >> >>>>> Thanks, >> >>>>> Brennon Bortz >>>>> Software Researcher >>>>> Dundalk Institute of Technology >>>>> brennon.bo... at casala.ie >>>>> Ph.D. Researcher & Composer - Sonic Arts Research Centre >>>>> Queen''s University, Belfast >>>>> bren... at brennonbortz.com / bbort... at qub.ac.uk >> >>>>> _______________________________________________ >>>>> rspec-users mailing list >>>>> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users >> >>>> Currently, what you''re doing is checking that the Widget model >>>> returns >>>> the correct widgets. If you want to isolate your controller spec from >>>> the model, you must stub or mock the model method call in the action. >>>> Example: >> >>>> it "..." do >>>> widget = mock_model(Widget) >>>> Widget.should_receive(:all).and_return([widget]) >>>> get :index >>>> assigns[:widgets].should include(widget) >>>> end >> >>>> To check that Widget.all does indeed return the correct widgets, I >>>> would spec that behaviour in the Widget model spec. >> >>>> Hope that helps. >> >>> Hrm...that''s exactly what I''d started with, and I was getting the >>> following error: >> >>> Failures: >>> 1) WidgetsController GET ''index'' should provide a collection of >>> widgets in @widgets >>> Failure/Error: assigns[:widgets].should include(widget) >>> expected [] to include #<Widget:0x81686290 @name="Widget_1001"> >> >>> Stupidly, I had defined my controller method as: >> >>> def index >>> @widgets = Widget.find(:all) >>> end >> >>> Changed that assignment to Widget.all...problem solved. >> >> And THAT is the problem with using mocks (or stubs) for this. You run >> the very real risk of specifying the implementation details in the >> structure of the spec/test. There is a problem when you''ve limited >> the refactoring that can be done without altering the spec/test. Since >> Widget.find(:all) and Widget.all should always have the same result, >> the mere presence of the mock has cut off one possible refactoring. >> (The one that I distaste most limits changing .find(params[:id]) >> to .find_by_id(params[:id]) by mocking/stubbing the call to find.) >> >> Think about what really needs to be specified and be careful to mock/ >> stub as little as possible and to do so in a way that will limit >> opportunities to refactor the least. >> >> -Rob >> >> Rob Biedenharn >> R... at AgileConsultingLLC.com http://AgileConsultingLLC.com/ >> r... at GaslightSoftware.com http://GaslightSoftware.com/ >> >> _______________________________________________ >> rspec-users mailing list >> rspec-us... at rubyforge.orghttp://rubyforge.org/mailman/listinfo/rspec-users > > The method you suggested does benefit refactoring. However, by not > stubbing or mocking, your controller is no longer in isolation. Which > means if Widget.all breaks, the model AND controller spec will fail. > > The are pros and cons to both ways. But what has pushed me to the > isolation side is that without mocking/stubbing, you must create a > record in the database (via fixtures or factories) and it is much > slower.Personally, I would use this as a driver to create a new method on Widget which did exactly what this controller wants, wrapping the details of the ActiveRecord API. That way, I have a nice, readable controller with fast, isolated, specs; a clear API on my models that makes sense in my domain; and if I want to change from a relational DB to a key-value store, I don''t have a dependency on ActiveRecord leaking out of my model all over the place.> _______________________________________________ > rspec-users mailing list > rspec-users at rubyforge.org > http://rubyforge.org/mailman/listinfo/rspec-userscheers, Matt http://blog.mattwynne.net +44(0)7974 430184
On Mon, Aug 30, 2010 at 14:09, Rob Biedenharn> And THAT is the problem with using mocks (or stubs) for this. ?You run the > very real risk of specifying the implementation details in the structure of > the spec/test. ?There is a problem when you''ve limited the refactoring that > can be done without altering the spec/test. Since Widget.find(:all) and > Widget.all should always have the same result, the mere presence of the mock > has cut off one possible refactoring. ?(The one that I distaste most limits > changing .find(params[:id]) to .find_by_id(params[:id]) by mocking/stubbing > the call to find.)On the contrary: by stubbing you''ve uncovered that you had used a low-level API (#find) instead of a high-level API (#all). This prompted you to make a conscious choice, which you did, and I prefer the choice you made, to invoke #all instead of #find. ?and THAT is the magic of using stubs and expectations for this. -- J. B. (Joe) Rainsberger :: http://www.jbrains.ca :: http://blog.thecodewhisperer.com Diaspar Software Services :: http://www.diasparsoftware.com Author, JUnit Recipes 2005 Gordon Pask Award for contribution to Agile practice :: Agile 2010: Learn. Practice. Explore.