==
сравнивает ссылки на объекты.
.equals()
сравнивает значения String.
Иногда ==
дает иллюзии сравнения значений String, как в следующих случаях:
String a="Test";
String b="Test";
if(a==b) ===> true
Это связано с тем, что при создании любого строкового литерала JVM сначала ищет этот литерал в пуле строк, и если он найдет совпадение, эта же ссылка будет передана новой String. Из-за этого получаем:
(a == b) ===> true
String Pool
b -----------------> "test" <-----------------a
Однако ==
не выполняется в следующем случае:
String a="test";
String b=new String("test");
if (a==b) ===> false
В этом случае для new String("test")
оператор new String будет создан в куче, и эта ссылка будет указана на b
, поэтому b
будет дана ссылка на кучу, а не на String pool.
Теперь a
указывает на String в пуле String, а b
указывает на String в куче. Из-за этого мы получаем:
, если (a == b) ===> false.
String Pool
"test" <-------------------- a
Heap
"test" <-------------------- b
Пока .equals()
всегда сравнивает значение String, поэтому дает true в обоих случаях:
String a="Test";
String b="Test";
if(a.equals(b)) ===> true
String a="test";
String b=new String("test");
if(a.equals(b)) ===> true
Таким образом, использование .equals()
всегда лучше.
Используя NUnit (не уверен насчет других), у вас есть следующий порядок выполнения:
TestFixtureSetup
Setup
Test
TearDown
Setup
Test
TearDown
TestFixtureTearDown
Каждый раз, когда вы запускаете свои тесты, они всегда будут выполняться в указанном порядке.
Если вы посмотрите на следующий код, вы увидите точную копию того, о чем я говорю. Вы даже можете скопировать и вставить этот код, и он должен работать (используя NUnit, не уверен, будет ли он работать с другими).
Если вы запустите это в режиме отладки и установите точку останова для каждого из методов, вы можете видеть порядок выполнения во время отладки.
using NUnit.Framework;
namespace Tester
{
[TestFixture]
public class Tester
{
public string RandomVariable = string.Empty;
[TestFixtureSetUp]
public void TestFixtureSetup()
{
//This gets executed first before anything else
RandomVariable = "This was set in TestFixtureSetup";
}
[SetUp]
public void Setup()
{
//This gets called before every test
RandomVariable = "This was set in Setup";
}
[Test]
public void MyTest1()
{
//This is your test...
RandomVariable = "This was set in Test 1";
}
[Test]
public void MyTest2()
{
//This is your test...
RandomVariable = "This was set in Test 2";
}
[TearDown]
public void TestTearDown()
{
//This gets executed after your test gets executed.
//Used to dispose of objects and such if needed
RandomVariable = "This was set in TearDown";
}
[TestFixtureTearDown]
public void TestFixtureTearDown()
{
//Executes Last after all tests have run.
RandomVariable = "This was set in TestFixtureTearDown";
}
}
}
Имейте в виду, что лучше всего сохранять отдельные тестовые наборы независимыми друг от друга. Таким образом, их можно понять, изменить и запустить независимо.
Некоторые считают настройку и демонтаж также плохой практикой. См. Эти ссылки для объяснения:
Для каждого класса, в котором у вас есть тесты, тестового устройства, вы можете указать 4 специальных метода. Имена методов на самом деле не важны, но вам нужно пометить методы одним из следующих четырех атрибутов, чтобы идентифицировать их.
Соглашение требует, чтобы вы вызывали методы так же, как атрибуты, но как я сказал, что атрибуты - это важный бит.
Обратите внимание, что описанные здесь атрибуты находятся в NUnit , но похожие атрибуты (если не такие же) используются в большинстве сред модульного тестирования.
Атрибуты:
Первые два имеют отношение к классу в целом. Метод, помеченный атрибутом TestFixtureSetUp
, запускается один раз перед первым тестом в классе.
После того, как все тесты в классе выполнены, метод, помеченный атрибутом TestFixtureTearDown
, выполняется один раз.
Вы можете использовать эти два для подготовки общих структур данных, которые одинаковы для все тесты и не изменяются никакими тестами (это важно).
Последние два, SetUp
и TearDown
, используются для обозначения двух методов, которые будут запускать до и после каждого отдельного теста.
Метод с тегом SetUp
вызывается перед каждым тестом, а метод с тегом TearDown
вызывается после каждого теста. Вы можете использовать их для подготовки общих структур данных, которые, несмотря на то, что они одинаковы для каждого теста, будут изменены некоторыми или всеми тестами, поэтому лучше подготовить новую новую копию для каждого теста.
Представление выполнения этих методов как псевдокода дает нам следующий порядок:
execute TestFixtureSetUp, if present
for each test do
execute SetUp, if present
execute actual test
execute TearDown, if present
execute TestFixtureTearDown, if present
Использование этих атрибутов совершенно необязательно. Вам не нужно иметь SetUp
, чтобы иметь TearDown
или наоборот. Это просто точки, в которых вы, возможно, захотите выполнить код.
Ознакомьтесь с документацией NUnit .
В меню внизу справа в разделе «Атрибуты» описаны [Настройка], [Тест] и другие атрибуты, которые вы можете использовать при разработке тестов.
В NUnit 2.5.1 порядок выполнения снова изменился. Я согласен с тем, что unittest никогда не должны мешать друг другу.