Как тестировать методы, работающие с private-полями

Efreeti

Новичок
Как тестировать методы, работающие с private-полями

Вопрос скорее к TDD infected.

Вот пример кода:
PHP:
class Logon {
	private $login = '';
	private $pwd = '';
	private $error = true;
	
	public function setLogin($str) {
		$this->login = $str;
	}
	
	public function setPassword($str) {
		$this->pwd = $str;
	}
	
	// Ещё методы для обработки, в том числе в них 
	// выставляется $this->error в true в случае ошибки
	
	public function getXml() {
		if ($this->error) {
			return '
<logon staus="error">
	<login value="'.$this->login.'">
	<password value="'.$this->pwd.'">
</logon>';
		}
		else {
			return '<logon staus="ok"></logon>';
		}
	}
}
Как стоит тестировать (unit-tests) методы setLogin(), setPassword(), getXml()?
Понятно, что на сеттеры можно забить (хоть и не хотелось бы), но третья функция имеет логику, которую может меняться, и её не хочется оставлять без тестов.

Я вижу 2 выхода:
а) Не объявлять поля приватными (но ухудшается инкапсуляция)
б) Не тестировать их в рамках unit-тестов, только в acceptance (т.е. не сами методы, а всё целиком).

Какие ещё есть идеи?
 

Efreeti

Новичок
Да, решение действительно красивое, о уж больно дорогое (в смысле времени на написание доп. кода).
Но тем не менее.

Пасиб Свет)
 

syfisher

TDD infected!!
Очевидно, что public интерфейсом данного класса является метод getXML(), почему бы не тестировать данный класс через него?

Обычно всегда, когда появляется необходимость тестирования закрытых методов или аттрибутов - это признак того, что нужно выделять отдельный класс или как-то рефакторить класс с целью повышения его тестируемости.
 

syfisher

TDD infected!!
Я правда не знаю, откуда взялся error атрибут, добавил поэтому метод check()...

PHP:
class LogonTest extends UnitTestCase
{
  function setUp()
  {
  // some stuff to make Logon class work as expected.
  }

  function testLogonSuccess()
  {
    $logon = new Logon();
    $logon->setLogin('vasa');
    $logon->setPassword('secret');
    $this->assertTrue($logon->check());
    $this->assertEqual($logon->toXML(), '<logon staus="ok"></logon>');
  }

  function testLogonError()
  {
    $logon = new Logon();
    $logon->setLogin('vasa');
    $logon->setPassword('no_such_password');
    $this->assertFalse($logon->check());
    $expected = '<logon staus="error"><login value="vasa"><password value="no_such_password"></logon>';
    $this->assertEqual($logon->toXML(), $expected);
  }
}
Ну если XML слишком сложный, тогда можно немного другими методами проверять, не просто посимвольно.
 

Efreeti

Новичок
syfisher
Хм. Ну в общем да.
Ладно, пока у меня мысли кончились, на практике проработаю - думаю ещё вопросы появяться.
 

Efreeti

Новичок
pachanga
Что-то он перебросил на главную, а там похожего я не нашёл.
 

.des.

Поставил пиво кому надо ;-)
запятую в конце линка уберите :)

-~{}~ 11.01.06 19:16:

А насчет тестирования методов работающих с приватными полями.
Почему бы вместо этих грязных хаков не использовать Reflection?
PHP:
$p = new ReflectionProperty('Logon', 'login');
var_dump($p->getValue($logon_object));
P.S. Хотя я и не TDD infected :) но что то мне подсказывает что в любом случае даже для тестов не нужно получать доступ к приватным полям.
 
Сверху