How simulate system users for testing file system interactions in ruby? - ruby

Im am quite happy to have found FakeFS to be able to fake a file system sandbox in which my tests can mess around. Now I want to be able to test test FileUtils.chown and chmod operations and therefor want to work with fake users in the test context and not tie my stuff to the operation systems user database to have fully portable and discrete tests.
I do my testing with rspec.
What would be the best way to do that?

I'm not sure I get the question, but I assume you want to test the "real" results of the FileUtils calls, i.e. changed permissions and ownership of files, that's why you need some kind of users. I wouldn't do that, since "SELECT isn't broken": http://pragmatictips.com/26
Instead, assume the following: if you call FileUtils.chown and friends with the right parameters, they will do the right thing. To make sure your application passes the correct parameters to FileUtils, use a mock. Here's an example: https://gist.github.com/phillipoertel/5020102
If you don't want to couple your test so closely to the implementation (the mock knows what's going on in your class internally) you could test the changed permissions by expecting it's effects. For example: if #user wasn't allowed to access #file before, call the method which changes permissions, then call one of your methods which require the changed permissions and assert that works. But this approach will access the filesystem, which you didn't want in the first place.

There is a very easy way to do this: FileUtils::DryRun. It's a module that acts just like FileUtils, but doesn't actually do anything to the filesystem for exactly these kinds of scenarios.
If you need it to replace FileUtils, just run FileUtils = FileUtils::DryRun

Related

It's correct to make a run method inside the class to start the flow of the 'program'?

I wrote this scraper script to extract the job list from a website. And then to in order to practice I decide to try to transform this script into a class object.
The correct approach is to just call the methods you need as it is below.
teste = InfoJobs.new
teste.build_url
teste.get_page_values
teste.scraping
teste.writing
but I want to know if is ok to have a run method inside of my class and use self. to make the flow of the scrape program.
def run
self.build_url
self.parsing(#url)
self.get_page_values
self.scraping
self.writing
end
teste.run
If you're asking "should I create an abstraction layer around the numerous steps required to perform the operation so that the caller doesn't need to care about the particulars" then the answer is that's fine.
I'd prefer to write code that says scraper.run than five lines of confusing boilerplate which doesn't afford me any more control than the equivalent run method does.

Can pundit policies be loaded from database?

I like the simplicity of Pundit gem and I would like to make policies dynamic by storing them to database.
Basically I'm looking for a way to be able to change policies without need to redeploy the application.
1st way
Pundit policy is pure ruby code, so if you don't want to keep code inside database and evaluate it dynamically, I'd say the answer is no. It's unsafe. You may give it a go, though.
2nd way
But nothing prevents you from creating model which keeps rules in simple json and compare them using Pundit, e.g.:
class PostPolicy < ApplicationPolicy
def update?
access_setting = PolicySetting.find_by(key: self.class_name)
user.role.in?(access_setting['roles'])
end
end
Of course, complexity and flexibility of the tool directly depends on each other.
3rd way
Is just work around. You may set you authorisation project apart from the main one, so that it's deploys (zero-downtime, of course) would not affect the main big project.
4th way
Create your own DSL to be stored in Database
5th way
Use something like json-logic-ruby to store logic in database

Alternatives to #VisibleForTesting

I understand that #VisibleForTesting is not desirable because it changes the interface of a class just for testing purposes. Ideally we should test the interface that we actually use. But what would be a good alternative?
You use #VisibleForTesting when, as you said, you want to test a part of code you're not exposing to the end user. If you want to test it then it most likely means it's complicated, or at least not trivial. Two solutions would be:
Split the method where you're calling this into several methods so you feel more comfortable about not having one big method doing a bunch of stuff at once.
See if you can move the behavior to an external object that takes care of it.
I like #2 a lot when stuff starts getting complicated, since I can have an external object that I can test and make sure it works without having to expose it through our interface.
Having said that, some times the behaviors don't warrant the extraction of the method into a new object and you use #VisibleForTesting just to save time. Experience is what tells you when it's worth it to do it (or not).

TDD: why, how and real world test driven code

First, Please bear with me with all my questions. I have never used TDD before but more and more I come to realize that I should. I have read a lot of posts and how to guides on TDD but some things are still not clear. Most example used for demonstration are either math calculation or some other simple operations. I also started reading Roy Osherove's book about TDD. Here are some questions I have:
If you have an object in your solution, for instance an Account class, what is the benefit of testing setting a property on it, for example an account name, then you Assert that whatever you set is right. Would this ever fail?
Another example, an account balance, you create an object with balance 300 then you assert that the balance is actually 300. How would that ever fail? What would I be testing here? I can see testing a subtraction operation with different input parameters would be more of a good test.
What should I actually test my objects for? methods or properties? sometime you also have objects as service in an infrastructure layer. In the case of methods, if you have a three tier app and the business layer is calling the data layer for some data. What gets tested in that case? the parameters? the data object not being null? what about in the case of services?
Then on to my question regarding real life project, if you have a green project and you want to start it with TDD. What do you start with first? do you divide your project into features then tdd each one or do you actually pick arbitrarily and you go from there.
For example, I have a new project and it requires a login capability. Do I start with creating User tests or Account tests or Login tests. Which one I start with first? What do I test in that class first?
Let's say I decide to create a User class that has a username and password and some other properties. I'm supposed to create the test first, fix all build error, run the test for it to fail then fix again to get a green light then refactor. So what are the first tests I should create on that class? For example, is it:
Username_Length_Greater_Than_6
Username_Length_Less_Than_12
Password_Complexity
If you assert that length is greater than 6, how is that testing the code? do we test that we throw an error if it's less than 6?
I am sorry if I was repetitive with my questions. I'm just trying to get started with TDD and I have not been able to have a mindset change. Thank you and hopefully someone can help me determine what am I missing here. By the way, does anyone know of any discussion groups or chats regarding TDD that I can join?
Have a look at low-level BDD. This post by Dan North introduces it quite well.
Rather than testing properties, think about the behavior you're looking for. For instance:
Account Behavior:
should allow a user to choose the account name
should allow funds to be added to the account
User Registration Behavior:
should ensure that all usernames are between 6 and 12 characters
should ask the password checker if the password is complex enough <-- you'd use a mock here
These would then become tests for each class, with the "should" becoming the test name. Each test is an example of how the class can be used valuably. Instead of testing methods and properties, you're showing someone else (or your future self) why the class is valuable and how to change it safely.
We also do something in BDD called "outside-in". So start with the GUI (or normally the controller / presenter, since we don't often unit-test the GUI).
You already know how the GUI will use the controller. Now write an example of that. You'll probably have more than one aspect of behavior, so write more examples until the controller works. The controller will have a number of collaborating classes that you haven't written yet, so mock those out - just dependency inject them via an interface. You can write them later.
When you've finished with the controller, replace the next thing you've mocked out in the real system by real code, and test-drive that. Oh, and don't bother mocking out domain objects (like Account) - it'll be a pain in the neck - but do inject any complex behavior into them and mock that out instead.
This way, you're always writing the interface that you wish you had - something that's easy to use - for every class. You're describing the behavior of that class and providing some examples of how to use it. You're making it safe and easy to change, and the appropriate design will emerge (feel free to be guided by patterns, thoughtful common sense and experience).
BTW, with Login, I tend to work out what the user wants to log in for, then code that first. Add Login later - it's usually not very risky and doesn't change much once it's written, so you may not even need to unit-test it. Up to you.
Test until fear is replaced by boredom. Property accessors and constructors are high cost to benefit to write tests against. I usually test them indirectly as part of some other (higher) test.
For a new project, I'd recommend looking at ATDD. Find a user-story that you want to pick first (based on user value). Write an acceptance test that should pass when the user story is done. Now drill down into the types that you'd need to get the AT to pass -- using TDD. The acceptance test will tell you which objects and what behaviors are required. You then implement them one at a time using TDD. When all your tests (incl your acc. test) pass - you pick up the next user story and repeat.
Let's say you pick 'Create user' as your first story. Then you write examples of how that should work. Turn them into automated acceptance tests.
create valid user -> account should be created
create invalid user ( diff combinations that show what is invalid ) -> account shouldn't be created, helpful error shown to the user
AccountsVM.CreateUser(username, password)
AccountsVM.HasUser(username)
AccountsVM.ErrorMessage
The test would show that you need the above. You then go test-drive them them out.
Don't test what is too simple to break.
getters and setters are too simple to be broken, so said, the code is so simple that an error can not happen.
you test the public methods and assert the response is as expected. If the method return void you have to test "collateral consequences" (sometimes is not easy, eg to test a email was sent). When this happens you can use mocks to test not the response but how the method executes (you ask the mockk if the Class Under Test called him the desired way)
I start doing Katas to learn the basics: JUnit and TestNG; then Harmcrest; then read EasyMock or Mockito documentation.
Look for katas at github, or here
http://codekata.pragprog.com
http://codingdojo.org/
The first test should be the easiest one! Maybe one that just force you to create the CUT (class under test)
But again, try katas!
http://codingdojo.org/cgi-bin/wiki.pl?KataFizzBuzz

Ideas on how to TDD application that needs to retrieve user name from system environment

How do you typically TDD aspects of your application that need to access operating system's system variables?
For example, my application needs to be able to correctly retrieve the operating system's currently-logged-in user name.
So I TDD a function that does this, and it's called:
string getUserNameFromSystemEnvironment();
The problem that I have is:
I'm running the test on my machine, so I know what the user name is (say FooBar). I TDD getUserNameFromSystemEnvironment() by hardcoding FooBar in my test like.
EXPECT_EQ(getUserNameFromSystemEnvironment(), "FooBar");
Clearly, this test runs okay on my machine, but not on others. To make it run fine on
others, however, I would need to use getUserNameFromSystemEnvironment(). But then, that kind of defeats the purpose of the test because we will have:
EXPECT_EQ(getUserNameFromSystemEnvironment(),
getUserNameFromSystemEnvironment());
Any ideas?
If you want to check this, you would need to set up a mock. Make an interface that returns the user ID, an implementation that calls getUserNameFromSystemEnvironment(), and a mock that returns whatever string you tell it to return.
But that's not really what you want to do. If you try to test getUserNameFromSystemEnvironment(), then you're effectively testing an operating system function. You don't need to test other people's code. Instead, put getUserNameFromSystemEnvironment() into an interface, and mock that for other parts of your system. Then, for example, to test LoginValidator, pass in a mock that returns usename as "Foobar", and verify that it validates the login. Then add a test that returns a username that should not validate and verify that it doesn't let it in.
Just ensure a value comes back, you don't always need to know what the exact value is.
Check the type is a string.
Check it's not null or empty.
Tests don't need to be 100% perfect, they just have to increase your confidence in the code.

Resources