#define It is a my subjective opinion. :)

(Maybe you can see many broken English.. please don't surprise, instead, let me know about the incorrect part. )



Why we need test?

 

Of course, we need test to verify the functions we made are right.


it's includes the real environment.

 

I used to do JUnit test and try to many abnormal methods to verify functions. 

(of course, I always thinking "how can i do test better?")


And I admit the facts below.

 

1. most of all, i want to test which use external resources. 


(in fact, i can get peaceful mind when this test was finished)

 

This test includes many resources such as network, database, and so on.


i'm usually did unit-test for this test.

 

2. For example, when i want to check some data in DB, but data not exist at first time.


Therefore, the insert operations are needed before select operation. however, can we confident that insert operation is success?


If so, how about insert some data to DB manually? (this way is... look so little complex or dirty..)

 

3. I can't think about test layer well.

 

Recently i realized that test have some layers and the below layer's object can be substituted by "mock".

 

So, what is test layer? 


Above picture is appeared in my brain.

 

There are two parts, one is needed test in real environment, another one is can be substituted by mock.


So, i like to summarized below as a result.

 

  • Unit Test: the tests are processed at each layer. and below layers are substituted by mock. 
  • Integration Test: the tests are use external resources. real environment required to do this test. 

And this is what i want to get by test,

 

Check your business logic and program structure by "Unit Test", check your real environment(resources) by "Integration Test"

Link

it is a really good article: The correct way to use integration tests in your build process


'프로그래밍 > JAVA' 카테고리의 다른 글

java goto문  (1) 2013.08.05
Map 읽기 전용으로 만들기  (0) 2013.04.25
Posted by DevMoon
,

lxml 설치하려다 생긴 문제.


OS X 10.9 매버릭스(Mavericks) 로 업그레이드 되면서 생기는 문제인 것같은데.

찾아보다가 해결책을 찾았다. 다음 명령 실행.


xcode-select --install


그런다음에 계속 설치해주면 된다.


sudo pip install lxml


출처: http://stackoverflow.com/questions/19548011/cannot-install-lxml-on-mac-os-x-10-9


TV

Posted by DevMoon
,

JAVA에서 2개 루프를 빠져나가려 하다가 goto문이 있나 검색해봤는데 같은 효과를 내는게 있었다. -_-;


출처: Is there a goto statement in java?


loops:
for (int i = 0; i < MAX_I; i++) {
    for (int j = 0; j < MAX_J; j++) {
        // do stuff
        break loops;
    }
}

굿잡~!


슈퍼맨

'프로그래밍 > JAVA' 카테고리의 다른 글

about test layer  (0) 2014.03.15
Map 읽기 전용으로 만들기  (0) 2013.04.25
Posted by DevMoon
,

method에서 map을 생성하자니 비효율적인 구조라는 의견이 있고


class로 빼자니, 다른 method에서 조작을 방지했으면 좋겠다는 의견이 있어 생각하다가 발견했다.


(어떤 정신나간 개발자가 method에서 이상한 값을 put 하는 그런 상황)


// class 변수
private final Map<string,string> MyMap;
...
// 생성자에서
HashMap<string,string> map = new HashMap<string,string>();
map.put("K", "1000");
map.put("M", "1000000");
MyMap = Collections.unmodifiableMap(map);


이와 같이 해주면 MyMap에 put 연산할 경우 예외가 발생하게 된다. (java.lang.UnSupportedOperation )


컴파일 시에 에러를 내주면 좋으련만..


이렇게 해도 경각심은 줄 수 있을 것같다.


참고 한 곳(링크) : How to create read only List, Map and Set in Java – unmodifiable example


생각중

'프로그래밍 > JAVA' 카테고리의 다른 글

about test layer  (0) 2014.03.15
java goto문  (1) 2013.08.05
Posted by DevMoon
,

table 이름이 table_1, table_2 .. 이런식으로 되어있을 때 table 번호를 바꿔가면서 데이터 수를 얻어오는 프로시저.


일일이 select 하기 번거로워서 찾아보다가 결국 답을 얻었다. :D


DELIMITER $$
CREATE PROCEDURE documentCount (
  IN p_start INT,
  IN p_end INT,
  IN id INT
)
BEGIN
  DECLARE table_iterator INT;
  DECLARE p_counter INT;
  
  SET p_counter = 0;
  SET table_iterator = p_start;

  WHILE table_iterator <= p_end DO
    SET @stm1 = CONCAT('SELECT count(*) INTO @tmp_counter FROM table_', table_iterator);
    SET @stm2 = CONCAT(' WHERE id=', id);
    SET @query = CONCAT(@stm1, @stm2);

    PREPARE get_count FROM @query;

    EXECUTE get_count;
    SET p_counter=p_counter+@tmp_counter;

    DROP PREPARE get_count;

    SET table_iterator = table_iterator + 1;
  END WHILE;
  SELECT p_counter;
END;
$$
DELIMITER ; 

참고한 사이트


http://www.sql.ru/forum/actualthread.aspx?tid=684898

Posted by DevMoon
,

branch들을 merge 한 후 몇 개 파일에서 conflict가 발생했고, 


파일 수정 후 commit 하려고 하니 다음과 같은 에러가 떴다.


svn: Commit failed (details follow):

svn: Aborting commit: 'xxxx' remains in conflict


경고 메시지에 포함된 경로에 가면 ".working", ".rxx" 파일들이 존재하는데 이 파일들을 삭제해주니 잘 된다.


- 좀 더 근본적으로 -


두 개의 branch를 merge 한 후 conflict가 발생하면 스프링 오른쪽 하단에 Merge Result view가 생긴다.


여기서 'show conflicts only' button을 누르면 conflict 나는 파일을 확인할 수 있다.


파일을 열어서 변경 내용을 확인한 후 닫으면 conflict 해결 여부를 묻는 창이 뜨는데 


거기서 적절히 선택해주면 된다.




예를 들어, 덮어쓰려는 파일말고 원래 있던 파일을 계속 유지하고 싶으면 이에 해당하는 옵션을 선택하면 된다.


그럼 알아서 conflict로 인해 생성된 파일들을 삭제 해준다.


처음에는 이걸 모르고 왼쪽 소스트리에 'x' 표시된 파일을 열어 


conflict 흔적(>>>> working .. 따위)을 지우다보니, conflict로 인해 생성된 파일이 그대로 남아있던 것이었다.

Posted by DevMoon
,

button을 클릭하면 javascript에서 form을 만들고, 여기에 child들을 쭈-욱 붙여서 서버로 날리고싶었다.


모든 기능이 잘 되고 있었는데 IE에서 하려고 하니, 버튼을 눌러도 안날라가는 상황이 발생.. 허허


다음과 같이 해주니 잘 날아간다.


...
document.body.appendChild(form);
form.submit();
document.body.removeChild(form);

참고한 곳 : 스택 오버플로우


Posted by DevMoon
,
이제 마지막 문제란다. -_-; 

어려운 문제가 나올까봐 긴장하긴 했지만 마지막이라니 왠지 아쉽네잉.


한 번 풀었다가 내가 문제를 잘못 해석한거라서 이전것은 말아먹었다 ㅜㅜ 


문제는 아래와 같다. (새창으로보기)



문제


사전에 등장하고 길이가 같은 두 단어가 주어졌을 때, 한 번에 글자 하나만 바꾸어 한 단어를 다른 단어로 변환하는 프로그램을 작성하라. 변환 과정에서 만들어지는 각 단어도 사전에 있는 단어여야 한다.

[실행 예]

input : DAMP, LIKE
output: DAMP -> LAMP -> LIMP -> LIME -> LIKE

[사전 데이터]

네 글자 단어 - word4

다섯 글자 단어 - word5

 

[심화 문제 - 풀지 않아도 됩니다]

심화문제 1: 가장 적은 수의 단어를 써서 변환하도록 프로그램을 작성해봅시다.

심화문제 2: 가장 많은 수의 단어를 써서 변환하도록 프로그램을 작성해봅시다. 단, 변환 과정에서 같은 단어가 두 번 나오면 안됩니다.


다른 사람들 보니 다들 그래프로.. 풀었길래 따라하는건 양심에 걸려서 새롭게 풀어보았다.


처음에 짰던 재귀형식으로 고민하다가 너무 오래 걸려서 새로운 전략을 짰다.


새로운 해결전략은 다음과 같다. (brand new!!)


1. 처음 element set에는 출발 단어 하나만 들어있다. 사전을 뒤적거리면서 distance가 1인 단어들을 모두 표시힌다.


2. 1번 과정에서 표시한 단어들과 distance가 1인 단어들도 모두 표시한다.


3. 더이상 새로운 단어가 추가되지 않을때까지 위 과정을 반복한다. 도중에 정답을 찾으면 바로 return.


한마디로 distance가 1인 집합에 계속해서 끌어들이는 방법이다.


이에따른 코드는 다음과 같다.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_WORD_NUM	8192
#define MAX_WORD_LEN	6

int nwords;
int elem[MAX_WORD_NUM];

char dic[MAX_WORD_NUM][MAX_WORD_LEN];

int makedic(char *fname)
{
	FILE *fp = NULL;

	fp = fopen(fname, "r");

	if (!fp) {
		printf("%s open fail.\n", fname);
		return 0;
	}

	int n = 0;

	while(1)
	{
		n = fscanf(fp, "%s", dic[nwords]);
		if (n == EOF) break;
		nwords++;
	}

	fclose(fp);
	return 1;
}

int distance(char *w1, char *w2, int len)
{
	int count = 0;

	for(int i = 0; i < len; i++) {
		if (w1[i] != w2[i]) {
			count++;
		}
	}

	return count;
}

int getpage(char *word)
{
	for(int i = 0; i < nwords; i++) {
		if (!strcmp(word, dic[i])) return i;
	}

	return -1;
}

int find(char *word, char *target, int len)
{
	int src_idx = getpage(word);

	if (src_idx == -1) return 0;

	elem[src_idx] = src_idx+1;

	while(1)
	{
		int find_newelem = 0;

		for(int i = 0; i < nwords; i++) 
		{
			if (elem[i])
			{
				for(int j = 0; j < nwords; j++)
				{
					if (elem[j] == 0 && distance(dic[i], dic[j], len) == 1)
					{
						// add new element.
						elem[j] = i+1;

						if (!strcmp(dic[j], target)) return j;

						find_newelem = 1;
					}
				}
			}
		}

		if (find_newelem == 0) break;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	if (argc != 2) {
		printf("Usage: %s dictionary\n", argv[0]);
		exit(1);
	}

	// make dictionary
	if (makedic(argv[1]) == 0) {
		printf("file open fail.\n");
		exit(1);
	}

	// get input
	char src[MAX_WORD_LEN], target[MAX_WORD_LEN];

	scanf("%s %s", src, target);

	// running...
	int rtn = find(src, target, strlen(src));

	if (rtn == 0) {
		printf("IMPOSSIBLE\n");
	} else {
		// make trace
		int idx = rtn, ntrace = 0;
		int trace[MAX_WORD_NUM];

		while(1)
		{
			trace[ntrace++] = idx;
			if (!strcmp(dic[idx], src)) break;
			idx = elem[idx]-1;
		}

		// print trace
		printf("%s", dic[trace[ntrace-1]]);

		for(int i = ntrace-2; i >= 0; i--) {
			printf(" -> %s", dic[trace[i]]);
		}
		printf("\n");
	}

	return 0;
}

trace를 위해서 elem이라는 배열에 어떤 단어로부터 왔는지 해당 index를 저장해두었다. (trace가 더 빡세...)

사전 파일을 보니 7천줄이 안되는 것같아 일단 메모리에 넣어두고 처리하기로 했다.

다음은 시험결과


shell> ./newdic word4.in

damp like

damp -> gamp -> gimp -> limp -> lime -> like


shell> ./newdic word4.in

acne mind

acne -> acre -> agre -> egre -> eire -> mire -> mine -> mind


shell> ./newdic word5.in

worse tasty

worse -> corse -> carse -> carte -> caste -> haste -> hasty -> tasty


shell> ./newdic word5.in

limit zorna

IMPOSSIBLE


damp like 입력에 대한 답이 예시 답안보다 길어서 맘에 안들긴 하지만 정답이긴 하니 뭐.


이제 심화 문제를 좀 더 고민해봐야지 -_-a


################################################################################################


심화문제 1(가장 적은 단어 사용하기) 해결~! 각 단어마다 distance를 저장해둘 필요가 있다. 


코드는 다음과 같이..

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAX_WORD_NUM	8192
#define MAX_WORD_LEN	6

int nwords;
int dist[MAX_WORD_NUM];
int from[MAX_WORD_NUM];

char dic[MAX_WORD_NUM][MAX_WORD_LEN];

int makedic(char *fname)
{
	FILE *fp = NULL;

	fp = fopen(fname, "r");

	if (!fp) {
		printf("%s open fail.\n", fname);
		return 0;
	}

	int n = 0;

	while(1)
	{
		n = fscanf(fp, "%s", dic[nwords]);
		if (n == EOF) break;
		nwords++;
	}

	fclose(fp);
	return 1;
}

int distance(char *w1, char *w2, int len)
{
	int count = 0;

	for(int i = 0; i < len; i++) {
		if (w1[i] != w2[i]) {
			count++;
		}
	}

	return count;
}

int getpage(char *word)
{
	for(int i = 0; i < nwords; i++) {
		if (!strcmp(word, dic[i])) return i;
	}

	return -1;
}

int find(char *src, char *target, int len)
{
	int src_idx = getpage(src);

	if (src_idx == -1) return 0;

	dist[src_idx] = 1;

	while(1)
	{
		int updated = 0;

		for(int i = 0; i < nwords; i++)
		{
			if (dist[i])
			{
				for(int j = 0; j < nwords; j++)
				{
					if (distance(dic[i], dic[j], len) == 1) 
					{
						// update distance
						if (dist[j] == 0 || dist[j] > dist[i]+1) 
						{
							dist[j] = dist[i]+1;
							from[j] = i;
							updated = 1;
						}
					}
				}
			}
		}

		if (updated == 0) break;
	}

	int target_idx = getpage(target);
	
	if (dist[target_idx]) {
		return target_idx;
	}

	return 0;
}

int main(int argc, char *argv[])
{
	if (argc != 2) {
		printf("Usage: %s dictionary\n", argv[0]);
		exit(1);
	}

	// make dictionary
	if (makedic(argv[1]) == 0) {
		printf("file open fail.\n");
		exit(1);
	}

	// get input
	char src[MAX_WORD_LEN], target[MAX_WORD_LEN];

	scanf("%s %s", src, target);

	// running...
	int rtn = find(src, target, strlen(src));

	if (rtn == 0) {
		printf("IMPOSSIBLE\n");
	} else {
		// make trace
		int idx = rtn, ntrace = 0;
		int trace[MAX_WORD_NUM];

		while(1)
		{
			trace[ntrace++] = idx;
			if (!strcmp(dic[idx], src)) break;
			idx = from[idx];
		}

		// print trace
		printf("%s", dic[trace[ntrace-1]]);

		for(int i = ntrace-2; i >= 0; i--) {
			printf(" -> %s", dic[trace[i]]);
		}
		printf("\n");
	}

	return 0;
}

다음은 시험결과


shell> ./newdic word4.in

damp like

damp -> lamp -> limp -> lime -> like


shell> ./newdic word4.in

acne mind

acne -> aune -> dune -> dine -> mine -> mind


shell> ./newdic word5.in

worse tasty

worse -> torse -> tarse -> tasse -> taste -> tasty


역시 결과가 달라졌다 음하핫. 시간은 좀 더 걸리지만..



Posted by DevMoon
,

이번 문제는 정말 꼼수(?)로 푼것같다 -_-; 한마디로 수학적인 검증? 철학? 이런게 없ㅋ엉ㅋ 


일단 나의 답. 다른 사람들과 비교하니 맞는 것같다.


2012! = 501 8

10000! = 2499 8


아래 책에서 나온 문제라는 것!!





문제는 아래와 같다. (새창으로보기)


자연수 n을 입력받고, n!의 계산 결과 중 마지막에 붙은 연속된 0의 개수와 연속된 0 바로 앞에 나오는 숫자를 구하라.

[실행 예]

input n: 15
output: 3 8

[설명]

15!은 1307674368000이므로, 마지막에 연속된 0은 3개이고, 바로 앞의 숫자는 8이다.

* 조건 *

  1. n의 범위는 1 이상, 10000 이하입니다.
  2. 테스트 입력은 다음과 같습니다.
    20! = 2432902008176640000
    30! = 265252859812191058636308480000000
    40! = 815915283247897734345611269596115894272000000000
    50! = 30414093201713378043612608166064768844377641568960512000000000000
    100! = 93326215443944152681699238856266700490715968264381621468592963
    8952175999932299156089414639761565182862536979208272237582511852
    10916864000000000000000000000000
  3. 프로그래밍 언어에서 제공하는 자릿수 제한 없는 곱셈을 이용하거나, 이런 형태의 곱셈 함수를 직접 구현해도 답을 얻을 수 있지만, 문제의 의도와는 다릅니다.
  4.  정답 검토의 편의를 위해 블로그 포스팅에 2012!와 10000!의 결과를 남겨주세요.
  5. (심화 문제) 연속된 0 앞에 나오는 여러 숫자를 구하는 것도 가능하니, 심심하신 분은 도전해보세요. ^^


저 어마어마한 숫자들을 다 저장한다는건 문제를 포기하겠다는 것이고 ..


생각해보니 0이 몇개인지를 카운트 해두고 앞에 몇자리 수만 기억해두면 될 것같았다. 


어차피 곱하기 할 때 앞자리 많은 수들은 0을 만들어내는 것과 관계가 없으므로. 


코드는 아래와 같이.. 짧게 @_@;

#include <stdio.h>

int main()
{
	int N = 0, zeros = 0;
	int mult = 1;

	scanf("%d", &N);

	for(int i=1; i<=N; i++) 
	{
		int div = 10;

		mult *= i;
		while(mult % div == 0) 
		{ 
			div *= 10; 
			zeros++;
		}

		mult /= (div/10);
		mult %= 100000;
	}

	printf("%d %d\n", zeros, mult%10);

	return 0;
}


Posted by DevMoon
,

첫 문제에 이어 두 번째 문제에 도전했다. (책표지 서비스~ 부탁받은대로~ㅋㅋ)


아래 책에 있는 문제라네.




두번째 문제는 개인적으로 너무 어려웠다. 아.. 남은 문제들은 어떻게 푸냐 -_-;;;


규칙을 찾는데 상당히 오래 걸렸는데 그 규칙은 다음과 같다.


1. 이전에 만들어진 집합에 현재 값을 포함시켜 새로운 집합으로 만든다. {} 쌍으로 된 것을 하나의 집합이라 한다.


2. 이전 집합과 별도로 독립적인 집합을 만든다. 그리고 그 결과를 취합한다.


ex) {0}에 {1}을 넣어야 하는 경우


기존 집합에 넣기: {0, 1}

독립적 집합 만들어 합치기: {0}, {1}


위에다 {2}를 넣으면?


기존 집합에 넣기: {0, 1, 2}, {0, 2}, {1, 2}

독립적 집합 만들어 합치기: {0, 1}{2}, {0}{1}{2}


...


이렇게 되는 것이다. 이걸 찾아내는게...참.. 후덜덜..ㅠㅠ


Python, C++, Perl 등 고차원 언어로 짜면 더 간단하게 표현 할 수 있겠지만 난 C로 짰다.


C로 구현하려니 독립적인 집합 표현하기가 힘들었다.


구조체를 이용하다가 코드가 지저분해져서 array의 index를 집합에 들어갈 값으로 하고, 


array 값을 집합 번호로 만들어 구현했다. 덕분에 코드는 좀 깔끔하게 나온듯하다.


#include <stdio.h>

//================================================
// TEST SET
//================================================
const int MAX_N = 16;
const int N = 4;
//================================================

int getMaxGroup(int *array, int size)
{
	int maxGroup = -1;

	for(int i = 0; i < size; i++) {
		if (array[i] > maxGroup) 
			maxGroup = array[i];
	}

	return maxGroup;
}

void printArray(int *array, int size)
{
	int maxGroup = getMaxGroup(array, size);

	for(int i = 0; i <= maxGroup; i++) 
	{
		printf("{");
		for(int j = 0; j < size; j++) {
			if (array[j] == i) {
				printf(" %d ", j);
			}
		}
		printf("}");
	}
	printf("\n");
}

void makeset(int *array, int size, int depth)
{
	if (depth == N) {
		printArray(array, size);
		return ;
	}

	// make new group 
	int maxGroup = getMaxGroup(array, size);

	array[depth] = maxGroup+1;
	makeset(array, size, depth+1);
	array[depth] = -1;

	// attach new element to each group
	for(int i = 0; i <= maxGroup; i++) {
		array[depth] = i;
		makeset(array, size, depth+1);
		array[depth] = -1;
	}
}

int main()
{
	int array[MAX_N];

	// init
	for(int i = 0; i < N; i++) {
		array[i] = -1;
	}

	makeset(array, N, 0);
	return 0;
}


어쨌든 풀어서 기분이 좋군 :)


실행결과


{ 0 }{ 1 }{ 2 }{ 3 }

{ 0  3 }{ 1 }{ 2 }

{ 0 }{ 1  3 }{ 2 }

{ 0 }{ 1 }{ 2  3 }

{ 0  2 }{ 1 }{ 3 }

{ 0  2  3 }{ 1 }

{ 0  2 }{ 1  3 }

{ 0 }{ 1  2 }{ 3 }

{ 0  3 }{ 1  2 }

{ 0 }{ 1  2  3 }

{ 0  1 }{ 2 }{ 3 }

{ 0  1  3 }{ 2 }

{ 0  1 }{ 2  3 }

{ 0  1  2 }{ 3 }

{ 0  1  2  3 }


Posted by DevMoon
,