I'm struggling with Test::Unit. When I think of unit tests, I think of one simple test per file. But in Ruby's framework, I must instead write:
我在测试:单元。当我想到单元测试时,我想到的是每个文件一个简单的测试。但是在Ruby的框架中,我必须这样写:
class MyTest < Test::Unit::TestCase
def setup
end
def test_1
end
def test_1
end
end
But setup and teardown run for every invocation of a test_* method. This is exactly what I don't want. Rather, I want a setup method that runs just once for the whole class. But I can't seem to write my own initialize() without breaking TestCase's initialize.
但是每次调用test_*方法时都要运行setup和teardown。这正是我不想要的。相反,我想要一个安装方法,对整个类只运行一次。但如果不破坏TestCase的initialize,我似乎无法编写自己的initialize()。
Is that possible? Or am I making this hopelessly complicated?
这有可能吗?还是我把事情弄得太复杂了?
10 个解决方案
#1
25
As mentioned in Hal Fulton's book "The Ruby Way". He overrides the self.suite method of Test::Unit which allows the test cases in a class to run as a suite.
正如哈尔·富尔顿在《Ruby之路》一书中提到的那样。他重写了自我。测试的套件方法::允许一个类中的测试用例作为一个套件运行的单元。
def self.suite
mysuite = super
def mysuite.run(*args)
MyTest.startup()
super
MyTest.shutdown()
end
mysuite
end
Here is an example:
这是一个例子:
class MyTest < Test::Unit::TestCase
class << self
def startup
puts 'runs only once at start'
end
def shutdown
puts 'runs only once at end'
end
def suite
mysuite = super
def mysuite.run(*args)
MyTest.startup()
super
MyTest.shutdown()
end
mysuite
end
end
def setup
puts 'runs before each test'
end
def teardown
puts 'runs after each test'
end
def test_stuff
assert(true)
end
end
#2
9
That's how it's supposed to work!
这就是它应该工作的方式!
Each test should be completely isolated from the rest, so the setup
and tear_down
methods are executed once for every test-case. There are cases, however, when you might want more control over the execution flow. Then you can group the test-cases in suites.
每个测试应该与其他测试完全隔离,因此对每个测试用例执行一次设置和tear_down方法。但是,有些情况下,您可能希望对执行流进行更多的控制。然后可以将测试用例分组到套件中。
In your case you could write something like the following:
你可以这样写:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class TestDecorator < Test::Unit::TestSuite
def initialize(test_case_class)
super
self << test_case_class.suite
end
def run(result, &progress_block)
setup_suite
begin
super(result, &progress_block)
ensure
tear_down_suite
end
end
end
class MyTestCase < Test::Unit::TestCase
def test_1
puts "test_1"
assert_equal(1, 1)
end
def test_2
puts "test_2"
assert_equal(2, 2)
end
end
class MySuite < TestDecorator
def setup_suite
puts "setup_suite"
end
def tear_down_suite
puts "tear_down_suite"
end
end
Test::Unit::UI::Console::TestRunner.run(MySuite.new(MyTestCase))
The TestDecorator
defines a special suite which provides a setup
and tear_down
method which run only once before and after the running of the set of test-cases it contains.
TestDecorator定义了一个特殊的套件,它提供了一个设置和tear_down方法,在它所包含的测试用例集运行之前和之后只运行一次。
The drawback of this is that you need to tell Test::Unit how to run the tests in the unit. In the event your unit contains many test-cases and you need a decorator for only one of them you'll need something like this:
这样做的缺点是您需要告诉Test::Unit how to run The testing in The Unit。如果您的单元包含许多测试用例,并且您只需要其中一个decorator,那么您将需要如下内容:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class TestDecorator < Test::Unit::TestSuite
def initialize(test_case_class)
super
self << test_case_class.suite
end
def run(result, &progress_block)
setup_suite
begin
super(result, &progress_block)
ensure
tear_down_suite
end
end
end
class MyTestCase < Test::Unit::TestCase
def test_1
puts "test_1"
assert_equal(1, 1)
end
def test_2
puts "test_2"
assert_equal(2, 2)
end
end
class MySuite < TestDecorator
def setup_suite
puts "setup_suite"
end
def tear_down_suite
puts "tear_down_suite"
end
end
class AnotherTestCase < Test::Unit::TestCase
def test_a
puts "test_a"
assert_equal("a", "a")
end
end
class Tests
def self.suite
suite = Test::Unit::TestSuite.new
suite << MySuite.new(MyTestCase)
suite << AnotherTestCase.suite
suite
end
end
Test::Unit::UI::Console::TestRunner.run(Tests.suite)
The Test::Unit documentation documentation provides a good explanation on how suites work.
测试::单元文档文档提供了一个关于套件如何工作的很好的解释。
#3
7
FINALLY, test-unit has this implemented! Woot! If you are using v 2.5.2 or later, you can just use this:
最后,测试单元实现了这一点!哇!如果您正在使用v2.5.2或更高版本,您可以使用以下内容:
Test::Unit.at_start do
# initialization stuff here
end
This will run once when you start your tests off. There are also callbacks which run at the beginning of each test case (startup), in addition to the ones that run before every test (setup).
这将在您开始测试时运行一次。除了在每个测试(安装)之前运行的回调之外,还有在每个测试用例(启动)的开头运行的回调。
http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html#at_start-class_method
http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html at_start-class_method
#4
2
Well, I accomplished basically the same way in a really ugly and horrible fashion, but it was quicker. :) Once I realized that the tests are run alphabetically:
嗯,我基本上是以同样的方式完成的,非常丑陋和可怕的方式,但它更快。)一旦我意识到测试是按字母顺序进行的:
class MyTests < Test::Unit::TestCase
def test_AASetup # I have a few tests that start with "A", but I doubt any will start with "Aardvark" or "Aargh!"
#Run setup code
end
def MoreTests
end
def test_ZTeardown
#Run teardown code
end
It aint pretty, but it works :)
它虽然不漂亮,但很管用:
#5
2
To solve this problem I used the setup construct, with only one test method followed. This one testmethod is calling all other tests.
为了解决这个问题,我使用了setup构造,后面只有一个测试方法。这个testmethod调用所有其他的测试。
For instance
例如
class TC_001 << Test::Unit::TestCase
def setup
# do stuff once
end
def testSuite
falseArguments()
arguments()
end
def falseArguments
# do stuff
end
def arguments
# do stuff
end
end
#6
2
I know this is quite an old post, but I had the issue (and had already written classes using Tes/unit) and ave answered using another method, so if it can help...
我知道这是一个相当古老的帖子,但是我有这个问题(并且已经用Tes/unit编写了类),而且ave使用了另一个方法来回答这个问题,所以如果可以的话……
If you only need the equivalent of the startup function, you can use the class variables:
如果您只需要等效的启动函数,可以使用类变量:
class MyTest < Test::Unit::TestCase
@@cmptr = nil
def setup
if @@cmptr.nil?
@@cmptr = 0
puts "runs at first test only"
@@var_shared_between_fcs = "value"
end
puts 'runs before each test'
end
def test_stuff
assert(true)
end
end
#7
1
I came across this exact problem and created a subclass of Test::Unit::TestCase
for doing exactly what you describe.
我遇到了这个问题,并创建了Test的子类:Unit::TestCase来完成您描述的工作。
Here's what I came up with. It provides it's own setup
and teardown
methods that count the number of methods in the class that begin with 'test'. On the first call to setup
it calls global_setup
and on the last call to teardown
it calls global_teardown
这是我想到的。它提供了自己的设置和拆解方法,用来计算以“test”开头的类中的方法数量。在第一次调用setup时,它调用global_setup,在最后一次调用teardown时,它调用global_teardown
class ImprovedUnitTestCase < Test::Unit::TestCase
cattr_accessor :expected_test_count
def self.global_setup; end
def self.global_teardown; end
def teardown
if((self.class.expected_test_count-=1) == 0)
self.class.global_teardown
end
end
def setup
cls = self.class
if(not cls.expected_test_count)
cls.expected_test_count = (cls.instance_methods.reject{|method| method[0..3] != 'test'}).length
cls.global_setup
end
end
end
Create your test cases like this:
创建这样的测试用例:
class TestSomething < ImprovedUnitTestCase
def self.global_setup
puts 'global_setup is only run once at the beginning'
end
def self.global_teardown
puts 'global_teardown is only run once at the end'
end
def test_1
end
def test_2
end
end
The fault in this is that you can't provide your own per-test setup
and teardown
methods unless you use the setup :method_name
class method (only available in Rails 2.X?) and if you have a test suite or something that only runs one of the test methods, then the global_teardown
won't be called because it assumes that all the test methods will be run eventually.
错的是你不能提供自己的每个测试设置和清除方法,除非你使用的设置:method_name类方法(仅可在Rails 2. x ?)如果你有一个测试套件或只运行一个测试方法,然后global_teardown不会被调用,因为它假设最终将运行所有的测试方法。
#8
0
Use the TestSuite as @romulo-a-ceccon described for special preparations for each test suite.
使用TestSuite @ romuo -a-ceccon来为每个测试套件进行特殊准备。
However I think it should be mentioned here that Unit tests are ment to run in total isolation. Thus the execution flow is setup-test-teardown which should guarantee that each test run undisturbed by anything the other tests did.
但是我认为应该在这里提到,单元测试是完全隔离运行的。因此,执行流是setup-test-teardown,它应该保证每个测试不受其他测试所做的任何干扰。
#9
0
I created a mixin called SetupOnce. Here's an example of using it.
我创建了一个名为SetupOnce的mixin。这里有一个使用它的例子。
require 'test/unit'
require 'setuponce'
class MyTest < Test::Unit::TestCase
include SetupOnce
def self.setup_once
puts "doing one-time setup"
end
def self.teardown_once
puts "doing one-time teardown"
end
end
And here is the actual code; notice it requires another module available from the first link in the footnotes.
这是实际的代码;注意,它需要从脚注中的第一个链接中获得另一个模块。
require 'mixin_class_methods' # see footnote 1
module SetupOnce
mixin_class_methods
define_class_methods do
def setup_once; end
def teardown_once; end
def suite
mySuite = super
def mySuite.run(*args)
@name.to_class.setup_once
super(*args)
@name.to_class.teardown_once
end
return mySuite
end
end
end
# See footnote 2
class String
def to_class
split('::').inject(Kernel) {
|scope, const_name|
scope.const_get(const_name)
}
end
end
Footnotes:
脚注:
-
http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html
http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html
-
http://infovore.org/archives/2006/08/02/getting-a-class-object-in-ruby-from-a-string-containing-that-classes-name/
#10
0
+1 for the RSpec answer above by @orion-edwards. I would have commented on his answer, but I don't have enough reputation yet to comment on answers.
+1是@orion-edwards给出的RSpec答案。我本想评论他的回答,但我还没有足够的声誉来评论答案。
I use test/unit and RSpec a lot and I have to say ... the code that everyone has been posting is missing a very important feature of before(:all)
which is: @instance variable support.
我经常使用测试/单元和RSpec,我不得不说……每个人发布的代码都缺少before(:all)的一个非常重要的特性:@instance变量支持。
In RSpec, you can do:
在RSpec中,您可以做到:
describe 'Whatever' do
before :all do
@foo = 'foo'
end
# This will pass
it 'first' do
assert_equal 'foo', @foo
@foo = 'different'
assert_equal 'different', @foo
end
# This will pass, even though the previous test changed the
# value of @foo. This is because RSpec stores the values of
# all instance variables created by before(:all) and copies
# them into your test's scope before each test runs.
it 'second' do
assert_equal 'foo', @foo
@foo = 'different'
assert_equal 'different', @foo
end
end
The implementations of #startup
and #shutdown
above all focus on making sure that these methods only get called once for the entire TestCase
class, but any instance variables used in these methods would be lost!
#startup和#shutdown的实现首先关注的是确保这些方法只在整个TestCase类中被调用一次,但是这些方法中使用的任何实例变量都将丢失!
RSpec runs its before(:all)
in its own instance of Object and all of the local variables are copied before each test is run.
RSpec在自己的对象实例中运行before(:all),在运行每个测试之前复制所有本地变量。
To access any variables that are created during a global #startup
method, you would need to either:
要访问在全局#启动方法中创建的任何变量,您需要:
- copy all of the instance variables created by
#startup
, like RSpec does - 复制#startup创建的所有实例变量,就像RSpec那样
- define your variables in
#startup
into a scope that you can access from your test methods, eg.@@class_variables
or create class-level attr_accessors that provide access to the@instance_variables
that you create inside ofdef self.startup
- 在#startup中定义变量到可以从测试方法访问的范围中,例如。@@class_variables或创建类级attr_accessors,它们提供对在def self.startup中创建的@instance_variables的访问
Just my $0.02!
只是我的0.02美元!
#1
25
As mentioned in Hal Fulton's book "The Ruby Way". He overrides the self.suite method of Test::Unit which allows the test cases in a class to run as a suite.
正如哈尔·富尔顿在《Ruby之路》一书中提到的那样。他重写了自我。测试的套件方法::允许一个类中的测试用例作为一个套件运行的单元。
def self.suite
mysuite = super
def mysuite.run(*args)
MyTest.startup()
super
MyTest.shutdown()
end
mysuite
end
Here is an example:
这是一个例子:
class MyTest < Test::Unit::TestCase
class << self
def startup
puts 'runs only once at start'
end
def shutdown
puts 'runs only once at end'
end
def suite
mysuite = super
def mysuite.run(*args)
MyTest.startup()
super
MyTest.shutdown()
end
mysuite
end
end
def setup
puts 'runs before each test'
end
def teardown
puts 'runs after each test'
end
def test_stuff
assert(true)
end
end
#2
9
That's how it's supposed to work!
这就是它应该工作的方式!
Each test should be completely isolated from the rest, so the setup
and tear_down
methods are executed once for every test-case. There are cases, however, when you might want more control over the execution flow. Then you can group the test-cases in suites.
每个测试应该与其他测试完全隔离,因此对每个测试用例执行一次设置和tear_down方法。但是,有些情况下,您可能希望对执行流进行更多的控制。然后可以将测试用例分组到套件中。
In your case you could write something like the following:
你可以这样写:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class TestDecorator < Test::Unit::TestSuite
def initialize(test_case_class)
super
self << test_case_class.suite
end
def run(result, &progress_block)
setup_suite
begin
super(result, &progress_block)
ensure
tear_down_suite
end
end
end
class MyTestCase < Test::Unit::TestCase
def test_1
puts "test_1"
assert_equal(1, 1)
end
def test_2
puts "test_2"
assert_equal(2, 2)
end
end
class MySuite < TestDecorator
def setup_suite
puts "setup_suite"
end
def tear_down_suite
puts "tear_down_suite"
end
end
Test::Unit::UI::Console::TestRunner.run(MySuite.new(MyTestCase))
The TestDecorator
defines a special suite which provides a setup
and tear_down
method which run only once before and after the running of the set of test-cases it contains.
TestDecorator定义了一个特殊的套件,它提供了一个设置和tear_down方法,在它所包含的测试用例集运行之前和之后只运行一次。
The drawback of this is that you need to tell Test::Unit how to run the tests in the unit. In the event your unit contains many test-cases and you need a decorator for only one of them you'll need something like this:
这样做的缺点是您需要告诉Test::Unit how to run The testing in The Unit。如果您的单元包含许多测试用例,并且您只需要其中一个decorator,那么您将需要如下内容:
require 'test/unit'
require 'test/unit/ui/console/testrunner'
class TestDecorator < Test::Unit::TestSuite
def initialize(test_case_class)
super
self << test_case_class.suite
end
def run(result, &progress_block)
setup_suite
begin
super(result, &progress_block)
ensure
tear_down_suite
end
end
end
class MyTestCase < Test::Unit::TestCase
def test_1
puts "test_1"
assert_equal(1, 1)
end
def test_2
puts "test_2"
assert_equal(2, 2)
end
end
class MySuite < TestDecorator
def setup_suite
puts "setup_suite"
end
def tear_down_suite
puts "tear_down_suite"
end
end
class AnotherTestCase < Test::Unit::TestCase
def test_a
puts "test_a"
assert_equal("a", "a")
end
end
class Tests
def self.suite
suite = Test::Unit::TestSuite.new
suite << MySuite.new(MyTestCase)
suite << AnotherTestCase.suite
suite
end
end
Test::Unit::UI::Console::TestRunner.run(Tests.suite)
The Test::Unit documentation documentation provides a good explanation on how suites work.
测试::单元文档文档提供了一个关于套件如何工作的很好的解释。
#3
7
FINALLY, test-unit has this implemented! Woot! If you are using v 2.5.2 or later, you can just use this:
最后,测试单元实现了这一点!哇!如果您正在使用v2.5.2或更高版本,您可以使用以下内容:
Test::Unit.at_start do
# initialization stuff here
end
This will run once when you start your tests off. There are also callbacks which run at the beginning of each test case (startup), in addition to the ones that run before every test (setup).
这将在您开始测试时运行一次。除了在每个测试(安装)之前运行的回调之外,还有在每个测试用例(启动)的开头运行的回调。
http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html#at_start-class_method
http://test-unit.rubyforge.org/test-unit/en/Test/Unit.html at_start-class_method
#4
2
Well, I accomplished basically the same way in a really ugly and horrible fashion, but it was quicker. :) Once I realized that the tests are run alphabetically:
嗯,我基本上是以同样的方式完成的,非常丑陋和可怕的方式,但它更快。)一旦我意识到测试是按字母顺序进行的:
class MyTests < Test::Unit::TestCase
def test_AASetup # I have a few tests that start with "A", but I doubt any will start with "Aardvark" or "Aargh!"
#Run setup code
end
def MoreTests
end
def test_ZTeardown
#Run teardown code
end
It aint pretty, but it works :)
它虽然不漂亮,但很管用:
#5
2
To solve this problem I used the setup construct, with only one test method followed. This one testmethod is calling all other tests.
为了解决这个问题,我使用了setup构造,后面只有一个测试方法。这个testmethod调用所有其他的测试。
For instance
例如
class TC_001 << Test::Unit::TestCase
def setup
# do stuff once
end
def testSuite
falseArguments()
arguments()
end
def falseArguments
# do stuff
end
def arguments
# do stuff
end
end
#6
2
I know this is quite an old post, but I had the issue (and had already written classes using Tes/unit) and ave answered using another method, so if it can help...
我知道这是一个相当古老的帖子,但是我有这个问题(并且已经用Tes/unit编写了类),而且ave使用了另一个方法来回答这个问题,所以如果可以的话……
If you only need the equivalent of the startup function, you can use the class variables:
如果您只需要等效的启动函数,可以使用类变量:
class MyTest < Test::Unit::TestCase
@@cmptr = nil
def setup
if @@cmptr.nil?
@@cmptr = 0
puts "runs at first test only"
@@var_shared_between_fcs = "value"
end
puts 'runs before each test'
end
def test_stuff
assert(true)
end
end
#7
1
I came across this exact problem and created a subclass of Test::Unit::TestCase
for doing exactly what you describe.
我遇到了这个问题,并创建了Test的子类:Unit::TestCase来完成您描述的工作。
Here's what I came up with. It provides it's own setup
and teardown
methods that count the number of methods in the class that begin with 'test'. On the first call to setup
it calls global_setup
and on the last call to teardown
it calls global_teardown
这是我想到的。它提供了自己的设置和拆解方法,用来计算以“test”开头的类中的方法数量。在第一次调用setup时,它调用global_setup,在最后一次调用teardown时,它调用global_teardown
class ImprovedUnitTestCase < Test::Unit::TestCase
cattr_accessor :expected_test_count
def self.global_setup; end
def self.global_teardown; end
def teardown
if((self.class.expected_test_count-=1) == 0)
self.class.global_teardown
end
end
def setup
cls = self.class
if(not cls.expected_test_count)
cls.expected_test_count = (cls.instance_methods.reject{|method| method[0..3] != 'test'}).length
cls.global_setup
end
end
end
Create your test cases like this:
创建这样的测试用例:
class TestSomething < ImprovedUnitTestCase
def self.global_setup
puts 'global_setup is only run once at the beginning'
end
def self.global_teardown
puts 'global_teardown is only run once at the end'
end
def test_1
end
def test_2
end
end
The fault in this is that you can't provide your own per-test setup
and teardown
methods unless you use the setup :method_name
class method (only available in Rails 2.X?) and if you have a test suite or something that only runs one of the test methods, then the global_teardown
won't be called because it assumes that all the test methods will be run eventually.
错的是你不能提供自己的每个测试设置和清除方法,除非你使用的设置:method_name类方法(仅可在Rails 2. x ?)如果你有一个测试套件或只运行一个测试方法,然后global_teardown不会被调用,因为它假设最终将运行所有的测试方法。
#8
0
Use the TestSuite as @romulo-a-ceccon described for special preparations for each test suite.
使用TestSuite @ romuo -a-ceccon来为每个测试套件进行特殊准备。
However I think it should be mentioned here that Unit tests are ment to run in total isolation. Thus the execution flow is setup-test-teardown which should guarantee that each test run undisturbed by anything the other tests did.
但是我认为应该在这里提到,单元测试是完全隔离运行的。因此,执行流是setup-test-teardown,它应该保证每个测试不受其他测试所做的任何干扰。
#9
0
I created a mixin called SetupOnce. Here's an example of using it.
我创建了一个名为SetupOnce的mixin。这里有一个使用它的例子。
require 'test/unit'
require 'setuponce'
class MyTest < Test::Unit::TestCase
include SetupOnce
def self.setup_once
puts "doing one-time setup"
end
def self.teardown_once
puts "doing one-time teardown"
end
end
And here is the actual code; notice it requires another module available from the first link in the footnotes.
这是实际的代码;注意,它需要从脚注中的第一个链接中获得另一个模块。
require 'mixin_class_methods' # see footnote 1
module SetupOnce
mixin_class_methods
define_class_methods do
def setup_once; end
def teardown_once; end
def suite
mySuite = super
def mySuite.run(*args)
@name.to_class.setup_once
super(*args)
@name.to_class.teardown_once
end
return mySuite
end
end
end
# See footnote 2
class String
def to_class
split('::').inject(Kernel) {
|scope, const_name|
scope.const_get(const_name)
}
end
end
Footnotes:
脚注:
-
http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html
http://redcorundum.blogspot.com/2006/06/mixing-in-class-methods.html
-
http://infovore.org/archives/2006/08/02/getting-a-class-object-in-ruby-from-a-string-containing-that-classes-name/
#10
0
+1 for the RSpec answer above by @orion-edwards. I would have commented on his answer, but I don't have enough reputation yet to comment on answers.
+1是@orion-edwards给出的RSpec答案。我本想评论他的回答,但我还没有足够的声誉来评论答案。
I use test/unit and RSpec a lot and I have to say ... the code that everyone has been posting is missing a very important feature of before(:all)
which is: @instance variable support.
我经常使用测试/单元和RSpec,我不得不说……每个人发布的代码都缺少before(:all)的一个非常重要的特性:@instance变量支持。
In RSpec, you can do:
在RSpec中,您可以做到:
describe 'Whatever' do
before :all do
@foo = 'foo'
end
# This will pass
it 'first' do
assert_equal 'foo', @foo
@foo = 'different'
assert_equal 'different', @foo
end
# This will pass, even though the previous test changed the
# value of @foo. This is because RSpec stores the values of
# all instance variables created by before(:all) and copies
# them into your test's scope before each test runs.
it 'second' do
assert_equal 'foo', @foo
@foo = 'different'
assert_equal 'different', @foo
end
end
The implementations of #startup
and #shutdown
above all focus on making sure that these methods only get called once for the entire TestCase
class, but any instance variables used in these methods would be lost!
#startup和#shutdown的实现首先关注的是确保这些方法只在整个TestCase类中被调用一次,但是这些方法中使用的任何实例变量都将丢失!
RSpec runs its before(:all)
in its own instance of Object and all of the local variables are copied before each test is run.
RSpec在自己的对象实例中运行before(:all),在运行每个测试之前复制所有本地变量。
To access any variables that are created during a global #startup
method, you would need to either:
要访问在全局#启动方法中创建的任何变量,您需要:
- copy all of the instance variables created by
#startup
, like RSpec does - 复制#startup创建的所有实例变量,就像RSpec那样
- define your variables in
#startup
into a scope that you can access from your test methods, eg.@@class_variables
or create class-level attr_accessors that provide access to the@instance_variables
that you create inside ofdef self.startup
- 在#startup中定义变量到可以从测试方法访问的范围中,例如。@@class_variables或创建类级attr_accessors,它们提供对在def self.startup中创建的@instance_variables的访问
Just my $0.02!
只是我的0.02美元!