Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ruby: Minitest, test-unit and instance variables

(Posted already at https://www.ruby-forum.com/topic/6876320, but crossposted here, because I did not receive a response so far).

A question about parallelizing tests in Minitest and/or Test::Unit (i.e. proper use of parallelize_me!):

Assume that I have some helper methods, which are needed by several tests. From my understanding, I could NOT do something like this in such a method (simplified example):

def prep(m,n)
 @pid = m
 @state = n
end

def process
 if @stat > 5 && @pid != 0
   ...
 else
   ...
 end
end

I think I can't do this in Minitest and test-unit, because if I call prep and process from several of my test function, the tests can not be parallelized anymore - those test functions all set and read the same instance variable. Right?

Now, my question is, whether the following approach would be safe for parallelization: I make all of these mutable instance variables a hash, which I initialized in setup like this:

def setup
  @pid ||= {}
  @state ||= {}
end

My "helper methods" receive a key (for example, the name of the test method) and use it to access the their "own" hash element:

def prep(key,m,n)
 @pid[key] = m
 @state[key] = n
end

def process
 if @stat[key] > 5 && @pid[key] != 0
   ...
 else
   ...
 end
end

It's a bit ugly, but: Is this a reliable approach? Is this way of accessing a hash thread-safe? How can I do it better?

like image 813
user1934428 Avatar asked Aug 06 '15 13:08

user1934428


People also ask

Can a Ruby module have instance variables?

In the Ruby programming language, an instance variable is a type of variable which starts with an @ symbol. An instance variable is used as part of Object-Oriented Programming (OOP) to give objects their own private space to store data.

How do you access instance variables in Ruby?

The instance variables of an object can only be accessed by the instance methods of that object. The ruby instance variables do not need a declaration. This implies a flexible object structure. Every instance variable is dynamically appended to an object when it is first referenced.

What is class variable and instance variable in Ruby?

Used declare variables within a class. There are two main types: class variables, which have the same value across all class instances (i.e. static variables), and instance variables, which have different values for each object instance.

How do I find the instance of a variable?

Instance variables can be accessed directly by calling the variable name inside the class. However, within static methods (when instance variables are given accessibility), they should be called using the fully qualified name.


1 Answers

At least in Minitest you can safely do, for example,

setup do
  @form = Form.new
end

without @form getting mixed up between parallel tests, so this approach should be safe too:

def setup
  @stat = m
  @pid = n
end

which means that your original approach should be safe as well.

================

UPDATE

consider the following gist with a piece of code that define 100 different tests accessing @random which is set in setup https://gist.github.com/bbozo/2a64e1f53d29747ca559

You will notice that the stuff set in setup isn't shared among tests, it is run before every test, basically every test is encapsulated so thread safety isn't an issue.

like image 117
bbozo Avatar answered Sep 25 '22 09:09

bbozo