The very first line written about sinatra is it is DSL for quickly creating web applications in Ruby with minimal effort. I can understand it is light weight, very flexible, quick for creating web apps and with minimal effort but not able to understand how it is a DSL?
One reason is that it defines actions ("verbs") within its domain as methods, for example:
get '/hi' do
"Hello World!"
end
Here Sinatra has incorporated an action from its domain--namely the HTTP request method "GET"--into its "vocabulary."
(Similar to building a library around banking and defining methods like account or customer.)
Is this more about the true definition of DSL?
Related
I've been looking for good practices for Rusy Sinatra and I found this question here on stackoverflow:
Using Sinatra for larger projects via multiple files
However, I am wondering what to do in case the business logic behind some route is big. Wouldn't be better to wrap it in a class (helper/utility) and just delegate to it from the route ?
I my opinion this will keep the controller clean and easy to follow.
What would be the best folder to place such a utility class ?
The pattern we use where I work is:
Sinatra Web Handler -> 'Processor' class (encapsulates business logic in a reusable route, sometimes behind facades). The processor does any ORM or cache operations which might be necessary, and knows when to delegate to further downstream processors (or, even, other internal / external services).
This decouples the sinatra routes from the application logic, and means that we can plug those processor classes. We try to keep the processor classes related to one business process, for e.g. User creation, and write them in such a way that we can plug them onto other endpoints as and when we desire. We're in effect using Sinatra as an HTTP request router into our main application.
It seems to work pretty well.
I just completed writing a detailed rspec capybara integration and unit tests for Rails app, which includes mocking Omniauth (twitter) login, filling in forms, data validations, etc. However, I am wondering whether there is a need to write a separate controller or functional test.
Would appreciate your input and any links to further readings etc.
I'll play devil's advocate here, since I know I'm probably in the minority with this opinion: I actually prefer to do exceedingly thorough controller testing. A few reasons:
1) I find it easier to systematically test every path and outcome at the controller level than at the integration test level. My integration tests are primarily just happy-paths, and some of the more common error paths.
2) A lot of potential security issues occur at the controller level. Thorough testing helps me ensure that nothing malicious can get through to my model logic.
3) This is subjective, but it really forces me to think about some of the long-tail paths that my application might go through. What if someone tries to for an invalid password reset token into the URL? Controller testing ensures that I consider all options.
4) Unlike integration tests, they're fairly straight-forward to test. Each action is just a ruby method!
Personally, I think if your request (integration) spec is exercising all code paths you're covered. Ryan Bates has a great Railscast about how he tests here: http://railscasts.com/episodes/275-how-i-test?autoplay=true and about 5:05 in he says a similar thing. Like you I like to write integration tests rather than controller specs. Most of the time controllers simply front CRUD type operations anyway (especially if you're careful about keeping domain logic out of the controller), so all you're testing is the scaffolding.
How do I access the app instance so I can test the foobar() method?
class App < Sinatra::Base
get '/' do
return foobar
end
def foobar
"hello world"
end
end
This is a late reply, but I am trying to find a flexible way to do that too.
I found in Sinatra's source code (1.4.5) that creating an instance of the app with new! allows testing the app's methods directly. Exert from a test setup with Test::Unit and Shoulda.
class AppTest < Test::Unit::TestCase
setup do
#app = App.new! # here is the point.
end
should 'say hello to the world' do
assert_equal "hello world", #app.foobar # or #app.send(:foobar) for private methods.
end
end
There are consequences. Using new! does not create the usual Sinatra::Wrapper that becomes the entry point to the middleware pipeline and the app in normal settings. So the new! approach will work only if the tested methods are really "helpers" that do not rely on middleware functionalities (e.g. SSL).
Alternatively, a post on Rspec proposes an alternative solution. I used something similar in the past, but it requires more work that is not always the best choice. It had the advantage to offer broader coverage of code to test. The isolation of the app with new! sounds good though, if we are taking about "unit" testing.
Note on #three's comment: A non-trivial app should separate API methods (usually in the app) from all helpers, etc. Helpers ending up in a separate file are cleaner, easier to maintain, and easier to test. But I definitely understand cases where a first version of an app would include a few helpers, with awareness that refactoring will be necessary. And even then having tests brings in some more confidence in the software itself, and in the future refactoring as well.
It doesn't matter what you test - it is how :) => http://www.sinatrarb.com/testing.html
I'm sick of writing out the same controller specs each time I make a new controller. I know I can use the scaffold generator, but there are enough little things I have to change that it usually doesn't save me much time.
Are there any projects/tools out there that provide some sort of base set of specs and/or a DSL to make this easier?
I've never found that any two REST controllers I wanted to write had similar enough interfaces that the tests were at all similar (and generally, I recommend Cucumber, not controller specs).
Something like inherited_resources or Rails 3's respond_with is very useful for writing the controllers, but I'm not sure about the tests.
I use the decent_exposure gem.
So I'm trying to figure out a way of stubbing a controller method in rspec for a Sinatra app. The main reason for this is to test the logical flow of the application and to make sure it calls the necessary functions when certain conditions are met. So, in essence, I want to be able to do something like
controller.should_receive(:fancy_method).and_return("This is a string")
What I'm having difficulty doing is accessing the controller instance within the sinatra app. I am able to override the current functions using a class_eval on the sinatra controller class, but I'd love to assert that these functions actually run.
Anyone have any advice?
Thanks.
Dan, I believe what you really want is to just test the controller actions. From a tester's perspective you shouldn't really care about what it actually called but rather for the output, given a specific input and maybe some other special conditions (that is mocking or stubbing other classes) (1).
You can check the official documentation for Sinatra + Rack::Test or this blog post from devver.net.
(1) : If your controller pages are calling some other classes (models, services, etc) you could mock these instead and put expectations on them. For example :
SomeClass.should_receive(:msg).with(:arg).and_return(:special_value)
Some more info for mocking (with RSpec in this exmaple) can be found on the RSpec documentation pages.